【问题标题】:Chaining promises with previous results将承诺与先前的结果链接起来
【发布时间】:2018-01-26 20:30:20
【问题描述】:

我正试图在此处How do I access previous promise results in a .then() chain?How do I access previous promise results in a .then() chain?

我已经设法使用 2 个 promise 来实现这一点,但是当我添加一个向 API 发出 POST 请求的 3rd 时,promise 结果是我的 post 请求,而不是来自该 post 请求的响应。

基本上我的应用程序的流程是。我将一个项目插入数据库。然后使用该 insertId 将多个项目插入到数据库中,这些项目是第一个 insertId 的“子项”。但我还需要将这些值发送到 API。然后,此 API 将返回另一个 ID,我最终会将其与我自己以前的 insertID 关联。代码大致如下(为简洁起见,我删除了一些其他逻辑和错误处理)。

let name = req.body.name;
let value = req.body.values;
let obj = {name:name};
let entries = [];
let a = db.items.insertItem(name);

let b = a.then((data) => {
    let insertId = data.insertId;
    let promises = [];
    values.forEach((val) => {
           entries.push({value:val)})
           promises.push( db.values.insertValuesForItem(insertId,val));
    })
    obj.entries = entries; 
    return promises;

})
let c =  b.then((data) => {
     return request.post(constants.devUrl,
    {
        headers:{
        'Authorization': 'bearer ' + constants.developerToken,
        'content-type': 'application/json'
        },
        json:obj
    });
});

Promise.all([a,b,c]).then(([resa,resb,resc]) => {
   //resc here contains the post request info e.g the post data and headers
   // what I really want from resc is the response from my post request
    res.redirect(200,'/items/' +  resa.insertId);
})

正如我之前提到的,在 resc 中,我实际上需要来自 API 请求的响应,而不是请求本身的详细信息。有什么想法可以实现吗?

【问题讨论】:

  • 你不是从b.then回调中丢失了data,因此丢失了你之前构建的promises数组吗?您不会在任何地方使用data,然后它就会丢失。我不明白你想用return promises实现什么
  • let b = ...。这里的 b 是一个承诺,当它被实现时,它会给我们promises 数组。所以在下面的语句b.then((data)... 中,data 实际上是承诺的数组。而且由于您在 b 成功回调中没有对 data 做任何事情,我不明白您为什么首先返回。
  • 我还希望 Jeremy 能够阅读我陈述我提出新问题的理由的问题,尤其是当我链接到已标记的问题时
  • request 使用什么库? post 不是在返回承诺吗?也许您可以将.then 链接到您的post() 返回值
  • 如果按原样使用则不会。如果你希望它返回一个承诺,你需要使用the following libs

标签: javascript promise


【解决方案1】:

现在问题重新打开,重申我在 cmets 中所说的话:

您的代码中有两个问题:

  1. 错误地链接承诺:

    let b = a.then((data) => {
        let insertId = data.insertId;
        let promises = [];
        values.forEach((val) => {
               entries.push({value:val)})
               promises.push( db.values.insertValuesForItem(insertId,val));
        })
        obj.entries = entries; 
        return promises; // this variable is accessed later as `data`, but
                         // never actually used => it's pointless
    
    })
    

    由于您返回 promises,实际上您返回的是 Promise只有在实现时,才会返回您的一系列承诺。这意味着:

    1. b 成功回调中,您将获得data(即promises 数组),但没有对其进行任何操作。
    2. Promise.all([a,b,c]).then(([resa,resb,resc]) 内部,resb 是承诺数组,而不是db 执行的结果。

    我了解您正在尝试同步执行,但这不是正确的方法。

  2. 错误地期望 request.post 返回一个承诺:

    let c =  b.then((data) => {
         return request.post(constants.devUrl,
        {
            headers:{
            'Authorization': 'bearer ' + constants.developerToken,
            'content-type': 'application/json'
            },
            json:obj
        });
    });
    

    正如您在 cmets 中提到的,您使用的是 this requests lib。因此,在这种情况下,c 确实是一个Promise,但它的返回值不是您所期望的httpResponse

    • 如果您想使用requests 以使其返回承诺,您需要使用these variances of the requests lib 之一,它正在返回承诺。

    • 但是,如果您不想更改库,则可以通过为 post 方法传递回调函数来同步执行。例如

      var gotResponseCallBack = function(err, httpResponse, body){
          return httpResponse;
      }
      request.post(constants.devUrl,
      {
          headers:{
          'Authorization': 'bearer ' + constants.developerToken,
          'content-type': 'application/json'
          },
          json:obj
      }, gotResponseCallBack); 
      

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多