【问题标题】:Correctly chaining Promises正确链接 Promise
【发布时间】:2023-03-26 16:38:02
【问题描述】:

我想在循环中按顺序绑定 Promise。我需要这个用户帐户,其中一个操作的结果取决于另一个。 我正在尝试编写一个平面版本 - 所有代码都在一个地方,使用绑定。这至少是我想要的。我将 promise 包裹在两个 create 方法中,如下所示:

function create(myApi, record) {
    return new Promise(function (resolve, reject) {
            myApi.create(record, function (err, result) {
                    if (err) reject(err);
                    else resolve(result);
            });
    });
}

function createUser(myApi, record) {
    return new Promise(function (resolve, reject) {
            myApi.createUser(record, function (err, result) {
                    if (err) reject(err);
                    else resolve(result);
            });
    });
}

现在,我想在循环中创建用户:

for ( var i = 0; i < dummyData.accounts.length; i++) {
  var cursorUser = dummyData.accounts[i];
  var auth0User = {
    email: cursorUser.email,
    password: cursorUser.password,
    connection: 'Username-Password-Authentication'
  };
  createUser(api, auth0User)
    .then( function(auth0Info) {
      console.log("Auth0 userInfo: ", auth0Info);
      cursorUser.authProfile = auth0Info;
      create(accountsAPIService, cursorUser)
        .then(function (account) {
          console.log("created account:", account);
        })
        .catch(function (err) {
          console.log('count not create account for user, error: ', err, '\nfor: ', auth0User);
        });
  })
  .catch(function (err) {
    console.log('could not create auth0 user, error: ', err, '\nfor: ', auth0User);
  });
}

由于这两种方法是异步的,所以当然不能正常工作。调用不是按顺序执行的。我想链接承诺,以便在 createUser 的调用返回之前 create 不会运行。尝试使用绑定,但它对我不起作用。应该如何进行顺序链接?我在createUser的.then上绑定?请指教。

【问题讨论】:

  • 嘿,ES6 是一种选择吗?如果这样的话,迁移到生成器会让你的生活变得更轻松
  • @itai 感谢您注意到我的问题。 ES6 可能是一个选择。无论如何,如果没有别的,我很想知道如何使用 ES6 做到这一点。
  • @MosheShmukler 写了答案希望它会有所帮助
  • @itai 是的,谢谢。我相信我已经弄清楚了如何使用 bind,但是很高兴知道事情在 es6 下是如何工作的。在工作中,我的同事用 babel 做了很多 typescript->es6->es5。目前对我来说太高级了,但我一定会尝试理解你的例子。

标签: javascript node.js promise


【解决方案1】:

当您从 then 返回承诺时,链接后的 then 将使用该承诺而不是原始承诺解决/拒绝。

createUser(api, auth0User).then(function(auth0Info) {
  cursorUser.authProfile = auth0Info;

  // Return create's promise
  return create(accountsAPIService, cursorUser);

}, function (err) {
  console.log('could not create auth0 user, error: ', err, '\nfor: ', auth0User);
})
// This will wait for create's promise instead of createUser's promise
.then(function (account) {
  console.log("created account:", account);
}, function (err) {
  console.log('count not create account for user, error: ', err, '\nfor: ', auth0User);
})

【讨论】:

  • 感谢您的回答。我不肯定你是正确的,在这里。至少我的数据看起来不对。我自己可能搞砸了。从我的测试来看,循环似乎没有在等待。
  • 我很确定这些承诺是并行执行的,而不是顺序执行的。然而,我对此一无所知,仍然不明白这个主题。我可能错了。
  • 你几乎就在现场。首先需要替换为绑定。
【解决方案2】:

使用 ES6,您可以使用生成器,它允许您编写异步任务,因为它们是异步的。在此示例中,我使用的是 bluebird,但 ofc 还有其他很好的有效选项。

var CreateUserGenerator = BPromise.coroutine(function * (arg) {
    for ( var i = 0; i < dummyData.accounts.length; i++) {
      var cursorUser = dummyData.accounts[i];
      var auth0User = {
        email: cursorUser.email,
        password: cursorUser.password,
        connection: 'Username-Password-Authentication'
    };
    var auth0Info =  yield createUser(api, auth0User);
    console.log("Auth0 userInfo: ", auth0Info);
    cursorUser.authProfile = auth0Info;
    var account = yield create(accountsAPIService, cursorUser)
    console.log("created account:", account);         
    }
}

function generateorWithCatch (argument) {
    creatLoopUser(arg)
    .catch(function (err) {
        console.log('could not create auth0 user, error: ', err, '\nfor: ', auth0User);
    });
}

在此解决方案中,我假设您的 create 和 createUser 函数已编写并正确返回值

【讨论】:

    猜你喜欢
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 2013-01-17
    相关资源
    最近更新 更多