簡體   English   中英

JavaScript承諾不會按順序觸發

[英]JavaScript promise not firing in order

我一直在嘗試有效地管理如何在Express.js應用程序中建立承諾。

現在,我有以下情形:在注冊過程中,用戶有一個可選的“ Organization Name字段。 如果已填寫,則需要創建Organization對象,然后將其_id添加到我要應用到該user的其他信息中。 如果沒有Organization name ,請繼續並更新基本user信息。

<-現在,在創建organization之前正在更新user ->

//basic info passed from the signup form
info['first_name'] = req.body.first_name;
info['last_name'] = req.body.last_name;
info['flags.new_user'] = false;

//if organization name is passed, create object and store _id in user object. 
let create_organization = new Promise(function(resolve, reject) {
  if (req.body.organization_name !== "") { //check if name is sent from form
    Organization.create({
      name: req.body.organization_name
    }, function(err, result) {
      console.log(result);
      if (!err) {
        info['local.organization'] = result._id;
        resolve()
      } else {
        reject()
      }
    })
  } else {
    resolve()
  }
});

let update_user = new Promise(function(resolve, reject) {
  User.update({
    _id: req.user._id
  }, info, function(err, result) {
    if (!err) {
      console.log("Updated User!"); < --prints before Organization is created
      resolve();
    } else {
      reject();
    }
  })
});

create_organization
  .then(function() {
    return update_user;
  })
  .then(function() {
    res.redirect('/dash');
  })

在開始進行后續工作之前,代碼中的任何內容都不會等待第一個承諾完成。 只要您調用User.update ,便開始工作,當您在promise執行程序中使用該代碼調用new Promise時,將同步完成該工作。

相反,請等到以前的承諾解決為止。 我可以通過將這些函數包裝在可重用的,啟用了createOrganization包裝器( createOrganizationupdateUser )中來做到這一點:

// Reusable promise-enabled wrappers
function createOrganization(name) {
    return new Promise(function(resolve, reject) {
        Organization.create({name: name}, function(err, result) {
            console.log(result);
            if (err) {
                reject(err);
            } else {
                resolve(result);
            }
        });
    });
}

function updateUser(id, info) {
    return new Promise(function(resolve, reject) {
        User.update({_id: id}, info, function(err, result) {
            if (err) {
                reject(err);
            } else {
                resolve();
            }
        })
    });
}

(您可以使用util.promisifypromisify npm模塊來避免手動執行此操作。)

接着:

//basic info passed from the signup form
info['first_name'] = req.body.first_name;
info['last_name'] = req.body.last_name;
info['flags.new_user'] = false;

//if organization name is passed, create object and store _id in user object. 
(req.body.organization_name === "" ? Promise.resolve() : createOrganization(req.body.organization_name))
.then(function() {
    return updateUser(req.user._id, info);
})
.catch(function(error) {
    // handle/report error
});

(由於您的代碼似乎正在這樣做,所以我堅持使用ES5級別的語法...)

請參閱傳遞給Promise構造函數的所謂的“執行函數”, 立即調用 這就是為什么您在兩個遠程過程調用之間實際上存在競爭條件的原因。 要解決此問題,請使更新負責創建promise:

function updateUser(userId, userInfo) {
  return new Promise(function(resolve, reject) {
    User.update({_id: userId}, userInfo, function(err, result) {
      if (err) { 
        reject(err);
      }
      else {
        resolve(result);
      }
    });
  });
}

...並在then()調用此函數。 這樣,只有在調用updateUser才會調用執行程序函數-並且將在createOrganization()完成其工作之后。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM