【问题标题】:Javascript BlueBird Promises: architecture for concurrent API requestsJavascript BlueBird Promises:并发 API 请求的架构
【发布时间】:2015-10-08 04:06:08
【问题描述】:

我正在寻求架构建议。在 MEAN 环境中使用 Bluebird Promises(这里说的是 node.js 服务器端),我打算进行许多并发 API 调用,聚合所有结果并响应客户端。示例(伪)代码:

exports.getAllData = function(searchquery, cb) {
    var results; 

   wrapper1.getResultsFromAPI1(searchquery, function(err,data){
    results += data;
   });

   wrapper2.getResultsFromAPI2(searchquery, function(err,data){
       results += data;
   });

   wrapper3.getResultsFromDataBase(searchquery, function(err,data){
       results += data;
   });

   if (AllRequests done){
       cb(null,results);
   }
}

现在我不知道如何确保:

  1. 同时触发所有请求(不按顺序触发以减少 响应时间)
  2. 收到所有 API 请求的响应后响应客户端
  3. 如果一个 API 请求由于某种原因失败,则不会拒绝整个承诺链,从而“丢失”其他 API 响应数据。

我在 Bluebird Promise 网站上查看了合适的集合,但似乎没有一个完全符合上面列出的要求。有什么建议吗?

【问题讨论】:

  • Promise.settle 应该可以。
  • 如果我错了,请纠正我,但只有在解决了承诺数组中的所有项目后,解决才会解决。有一次,一个项目(在我的例子中:一个 API 调用)失败了,整个 Promise 链都失败了。这不是我需要的。
  • @IgorP。 Promise.all 将在通过的 Promise 之一失败时失败。 Promise.settle 将为您提供一个数组作为结果,其中包含哪些承诺被拒绝以及哪些承诺被解决的信息。所以你将你的settle 看看是否所有的请求都真的完成了。
  • 哦,好的。那我一定是误解了网上的参考资料。我会试一试。谢谢=)

标签: javascript promise bluebird


【解决方案1】:

一种方法是使用reflect 调用。

var Promise= require('bluebird');

Promise.props({
  "wrapper1": someasync(1).reflect(),
  "wrapper2": someasync(0).reflect(),
  "wrapper3": someasync(1).reflect()
})
.then(function(results) {
  Object.keys(results).forEach(function(key) {
    if (results[key].isRejected()) {
      console.log(key + " failed.", results[key].reason());
    } else {
      console.log(key + " successed", results[key].value());
    }
  });
});

function someasync(t) {
  if (t===0) return Promise.reject('some err');
  else return Promise.resolve(true);
}

结果如下:

wrapper1 successed true
wrapper2 failed. some err
wrapper3 successed true

【讨论】:

  • @Bergi 一个评论,好吗? :)
【解决方案2】:
var Promise= require('bluebird');
var chain = require('lodash').chain;

function rejectedPromise(settledPromise) {
    return settledPromise.isRejected(); 
}

function extractResponse(fulfilledPromise) {
    return fulfilledPromise.value();
}

Promise.settle([
    asyncCall(),  
    asyncCall(),  
    asyncCall() 
])
.then(function retrieveSuccessfulResponses(settledPromises) {
    return chain(settledPromises)
        .reject(rejectedPromise)  
        .map(extractResponse)
});

【讨论】:

    【解决方案3】:

    如果您愿意,您可以手动承诺您的 API 方法,例如:

    var p1 = new Promise(function(resolve, reject) {
      wrapper1.getResultsFromAPI1(searchquery, function(err, data) {
        if (err) reject(err);
        else resove(data);
      });
    });
    

    但是由于您使用的是 BlueBird 库,因此您可以使用 Promise.promisify,这样您就可以避免将方法包装到 Promise 中的样板代码。例如:

    var getResultsFromAPI = Promise.promisify(wrapper1.getResultsFromAPI1);
    var p1 = getResultsFromAPI(searchquery);
    

    如果你想promisify一个API的所有方法,你可以使用Promise.promisifyAll。例如:

    var wrapper1 = Promise.promisifyAll(require('my-api'));
    
    // then, all the wrapper1 methods are already wrapped into a Promise
    var p1 = wrapper1.getResultsFromAPI1(searchquery);
    

    因此,将所有方法转换为 Promise 后,您可以使用 Promise.settle 来实现您想要的:查看哪些承诺已实现,哪些被拒绝:

    exports.getAllData = function(searchquery, cb) {
      /* Don't forget to promisify all the API methods firstly */
    
      var results;
    
      var p1 = wrapper1.getResultsFromAPI1(searchquery);
      var p2 = wrapper2.getResultsFromAPI2(searchquery);
      var p3 = wrapper3.getResultsFromDataBase(searchquery);
    
      Promise.settle([p1, p2, p3]).then(function(arr) {
        arr.forEach(function(res, index) {
          if (res.isFulfilled()) {     // check if the Promise was fulfilled
            results += res.value();    // the Promise's return value
          }
          else if (res.isRejected()) { // check if the Promise was rejected
            console.log(res.reason()); // do something with the error
          }
        });
    
        cb(null, results);
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-17
      • 1970-01-01
      • 2014-10-08
      • 2011-11-09
      相关资源
      最近更新 更多