节点js聚合10个异步调用的响应

时间:2017-11-22 18:30:01

标签: javascript node.js promise

我们要求基于查询参数数组(contentId [] = 1& contentId [] = 2 ....等)构建api调用,然后将异步调用附加到api终点例如http://xxxx/content/contentId

基于响应,我们需要聚合并用内容contentId包装内容,我们在点击各个api端点时收到的响应代码

{
 { "contentd": "1",
 "responsecode": 200,
"messsage": "",
content{
}
}

{ "contentd": "2",
 "responsecode": 200,
"messsage": "",
content{
}
...
}

我们正在使用诺言做同样的事情。我使用了承诺如下。

Promise.all(req.query.contentId
        .map(function (contentId) {
          console.log('processing the content id'+contentId);
          return getContent(contentId);
        }))
      .then(function (all_content) {

        //convert each resolved promised into JSON and convert it into an array.

        res.json(all_content.map(function (content) {

          return JSON.parse(content)
        }));
      })

      .catch(function(rej) {
      //here when you reject the promise
      console.log("404 received"+rej);


    }) ;
  } catch (e) {
    res.send(e.message);
  }
});

// this is the function that makes the call to the backend. Note usage of request promise
function getContent(contentId) {
  console.log('content id received to fetch the content'+contentId);
  var options = {
    uri: 'http://xxxxx/api/content/'+contentId,
    headers: {
        'Authorization': 'Basic YWRtaW46YWRtaW4='
    },
    qs: {

      _format: 'json'

    }
  };
  return rp(options);
}

问题 - 我们面临的问题是,当我们将http状态代码设置为200时,对于调用,结果很好。但是,对于http状态代码404(未找到),不进行处理。它似乎很快就失败了。

另外,如何在JSON.parse中处理内容响应时插入自己的响应,状态字段。感谢

2 个答案:

答案 0 :(得分:1)

如果您阅读Promise.all(),那就是它的作用。如果您通过的任何承诺拒绝,它会立即拒绝整体Promise.all()承诺,并且您不会获得其他结果。

如果你想要所有其他结果,你必须提前捕获任何拒绝,以便Promise.all()永远不会看到它们或使用不同的方式跟踪旨在获得所有响应的所有承诺,无论是否有任何拒绝或不。

你可以早点发现拒绝"隐藏"它通过执行类似的操作形成Promise.all(),您还必须跳过通过的任何错误对象的JSON.parse()

Promise.all(req.query.contentId
    .map(function (contentId) {
      console.log('processing the content id'+contentId);
      // catch errors here and make the resolved value be the error object
      // so Promise.all() processing continues on the other requests
      return getContent(contentId).catch(e => e);
    }))
  .then(function (all_content) {

    //convert each resolved promised into JSON and convert it into an array.

    res.json(all_content.map(function (content) {
      // make sure we don't try to parse things that are already objects
      // like error objects
      if (typeof content !== "string") {
          return content;
      } else {
          return JSON.parse(content);
      }
    }));
  }).then(function(results) {
    // remove any error objects
    // and probably log them to so they aren't just silently eaten
    return results.filter(item => !(item instanceof Error));
  })

然后,在使用此结果数组的同时下游,您需要跳过结果中的任何错误对象。

或者,您可以将结果转换为某种无操作结果,这种结果不会影响您的下游处理,或者您可以构建一个不同的数组,将所有错误结果从中过滤掉。

而且,如果你想要一些预先编写的代码来获取所有的响应(包括错误结果),那通常称为Promise.settle()。您可以在此处使用Promise.settle()的多个实现:

ES6 Promise.all() error handle - Is .settle() needed?

  

另外,如何在JSON.parse中处理内容响应时为响应,状态插入自己的字段。

你可以改变这个:

return JSON.parse(content);

这样的事情:

let obj = JSON.parse(content);
obj.someOtherProp = 'myvalue';
return obj;

答案 1 :(得分:0)

 return getContent(contentId);

在这里,您将向Promise.all返回承诺。因此,如果promise失败,它将触发Promise.all catch并且所有路由都失败。所以我们需要提前赶上,所以就在那里:

return getContent(contentId).catch( e => e);

这意味着如果出现错误,请继续执行错误。由于JSON.parse失败,您可以返回一个json字符串:

return getContent(contentId).catch( e => '{"error":500}');

关于第二个问题:

您可能希望为返回的结果分配其他属性:

return Object.assign( JSON.parse(content), {
  what: "ever"
});