繁体   English   中英

Javascript BlueBird承诺:并发API请求的体系结构

[英]Javascript BlueBird Promises: architecture for concurrent API requests

我正在寻找架构建议。 我打算在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网站上检查了适当的收藏,但似乎没有一个完全满足上面列出的要求。 有什么建议么?

一种方法是使用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
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)
});

如果需要,您可以手动使用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);

而且,如果您希望对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);

因此,在将所有方法转换为Promises之后,您可以使用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);
  });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM