将承诺的结果链接并传递给进一步的承诺[重复]

Posted

技术标签:

【中文标题】将承诺的结果链接并传递给进一步的承诺[重复]【英文标题】:Chaining and passing result of promise to a promise further down [duplicate] 【发布时间】:2017-11-28 08:16:02 【问题描述】:

我正在链接一些返回承诺的请求。第一个是对某个站点的登录检查,该站点返回一些凭据。然后我打了一个 admin.auth().createUser() 电话。在我知道这个 createUser 调用成功并且我知道登录检查成功之后,我想使用从两个 promise 返回的这两个对象来发出第三个请求,以将信息存储在 firebase 实时数据库中。我只是不知道如何将这两个结果传递给最终的承诺。这是一些代码。

login(siteUser, sitePass)
   .then(credentials => 
      return admin.auth().createUser(
         'email': email,
         'emailVerified': false,
         'password': password,
         'displayName': username
       )
    )
    .then(userData => 
       return writeUserData(userData, credentials); // I need to pass credentials here but I don't know how.
    )
    .then(() => res.status(200).send('success'))
    .catch(err => res.status(500).send(err));

我需要在 createUser() 解析后将第一个承诺的结果传递给 writeUserData。

【问题讨论】:

userRecord 中的 writeUserData(userRecord, credentials) 是什么?为什么userData 被忽略?你不需要createUser的结果吗? 呜呜它应该是 userData 【参考方案1】:

这在功能上与您的代码相同,只是它将credentials 传递到writeUserData 需要它的位置。不是完全平坦的承诺链,而是将 .then 添加到 createUser 响应以返回 credentials,而不是来自 createUser

unused(在您的代码中)响应
login(siteUser, sitePass)
.then(credentials => 
    admin.auth().createUser(
        email, 
        emailVerified:false, 
        password, 
        displayName: username
    )
    .then(userData => credentials)
)
.then(credentials => writeUserData(userRecord, credentials))
.then(() => res.status(200).send('success'))
.catch(err => res.status(500).send(err));

但是,如果您在代码中犯了错误并且

.then(userData => 
   return writeUserData(userRecord, credentials); // I need to pass credentials here but I don't know how.
)

应该是

.then(userData => 
   return writeUserData(userData, credentials); // I need to pass credentials here but I don't know how.
)

(即 userRecord 应该是 userData) - 那么您不会忽略来自 createUser 的响应 - 这根本不会使代码变得更加复杂

login(siteUser, sitePass)
.then(credentials => 
    admin.auth().createUser(
        email, 
        emailVerified:false, 
        password, 
        displayName: username
    )
    .then(userData => (userData, credentials))
)
.then((userData, credentials) => writeUserData(userData, credentials))
.then(() => res.status(200).send('success'))
.catch(err => res.status(500).send(err));

【讨论】:

谢谢!是的,这是一个错字 酷,所以最后一个代码块应该可以工作 这没有按原样工作。我需要在 admin.auth 之前添加 return。喜欢@shivam 的解决方案 在这种情况下,您错误地复制了代码,返回时会出现语法错误,因为我使用的是具有隐式 return 的速记箭头函数符号 - 请注意完全缺少 @ 987654332@=>之后的@ 哦,我现在明白了。还有一件事。如何从返回的 admin.auth().createUser() 中正确捕获错误?如果我只是添加一个 catch 并尝试执行 res.send(err),那么外部就会被执行。如何在内部 catch 中完成调用或将 catch 传递给外部?【参考方案2】:

你可以试试这个。你需要使用Promise.all

const loginPromise = login(siteUser, sitePass);
const createUserPromise = admin.auth().createUser(
  'email': email,
  'emailVerified': false,
  'password': password,
  'displayName': username
)

Promise.all([loginPromise, createUserPromise]).then(result => 
    // Then use result array
    return writeUserData(result[1], result[0]);
  ).then(() => res.status(200).send('success'))
  .catch(err => res.status(500).send(err));

【讨论】:

这将基本上并行执行 logincreateUser - 如果您将这些函数名称表示为它们的作用,这可能会导致问题:p【参考方案3】:

Maaz 的 Promise.all 解决方案也可以使用,除非您需要从登录请求到 createUser 请求中的某些内容。如果是这样,那么您可以使用下面的解决方案。

login(siteUser, sitePass)
.then(credentials => 
  return admin.auth().createUser(
     'email': email,
     'emailVerified': false,
     'password': password,
     'displayName': username
   )
  .then(createUserRes => (createUserRes, credentials)
)
.then(userData => 
    // You can now access both the createUserRes & credentials as
    // userData.credentials or userData.createUserRes
   return writeUserData(userRecord, credentials); // I need to pass credentials here but I don't know how.
)
.then(() => res.status(200).send('success'))
.catch(err => res.status(500).send(err));

【讨论】:

以上是关于将承诺的结果链接并传递给进一步的承诺[重复]的主要内容,如果未能解决你的问题,请参考以下文章

PromiseKit 2.0:链接承诺不传递参数

如何按顺序执行承诺并返回所有结果[重复]

你如何将 setTimeout 包装在一个承诺中[重复]

如何在线性流之后链接承诺?

承诺,如何将变量传递给 .then 函数

承诺解决并将道具传递给嵌套子项时如何更新Vue组件