使用Bluebird.mapSeries顺序处理一系列API调用

时间:2018-03-02 07:38:12

标签: javascript promise bluebird

我一直在尝试的是按顺序处理API调用,这些调用将被推送到数组中。

function resolveApi(callback) {
  return new Promise(function(resolve, reject) { resolve(callback) });
}

function callApi(){

    var promises = [];
    promises.push(resolveApi(Restangular.one("api/blahblah",{/*input data*/})));
    promises.push(resolveApi(Restangular.one("api/another/api",{/*input data*/})));
    //there are other similar API calls.
    //Restangular is supposed to return an API call

    promises = Bluebird.mapSeries(promises, function(item, index) {
        return item;     
    });

    promises.then(function(){/* the end */});
}

目标是处理promises数组中的每个API调用,但上面的代码不会这样做。 (即API调用几乎同时被调用,而每个API调用应该等到前一个调用完成。)

你看到我做错了吗?

任何建议都将受到赞赏。

2 个答案:

答案 0 :(得分:1)

resolveApi(Restangular.one("api/blahblah",{/*input data*/}))不是真正的承诺,它会立即恢复callback

我想你想在ajax成功之后解决,Promise.all并行运行这是最快的方式,如下所示:



Promise.all([
  Restangular.one("api/blahblah", { /*input data*/ }),
  Restangular.one("api/blahblah", { /*input data*/ }),
  ...
]).then((resultArray) => {
  //all finish
  console.log(resultArray)
}).catch((e) => {
  console.log(e)
})




或顺序



Promise.mapSeries([
  ["api/blahblah", { /*input data*/ }],
  ["api/blahblah", { /*input data*/ }],
  ...
], (item) => Restangular.one(item[0], item[1])).then(() => {
  //done
}).catch((e) => {

})




以及更多,你可能想在下一个ajax中使用一个ajax的结果,你可以使用 https://www.npmjs.com/package/chain-promise,代码可能看起来像



var chainPromise = require("chain-promise");

const params = [
  ["api/blahblah"],
  ["api/blahblah"],
]

chainPromise(params.map((p) => {
  return (data) => Restangular.one(p[0], data)
}), initData).then(() => {
  console.log('done')
}).catch((e) => {
  console.log(e)
})




答案 1 :(得分:0)

好吧,你可以使用一个小的递归实用程序来一个接一个地对promise进行排序。我这里有两个实现

  1. 如果抛出任何错误,这个将处理错误并继续下一个承诺。我使用.finally(),因此请确保您的浏览器是最近的。
  2. var simulatePromisifiedAPI = (delay,data) => new Promise((v,x) => setTimeout(_ => Math.random() > 0.1 ? v(data) : x(`error @ ${data}`), delay)),
        promises               = Array(10).fill(simulatePromisifiedAPI),
        sequencePromises       = ([api,...apis]) => apis.length ? api(250,`task no ${10-apis.length}`).then(v => console.log(`Doing something with the API data ${v}`))
                                                                                                      .catch(e => console.log(`Opps... Just got ${e}`))
                                                                                                      .finally(_ => sequencePromises(apis))
                                                                : api(250,"final").then(v => console.log(`Doing something with the API data ${v}`))
                                                                                  .catch(e => console.log(`Opps... Just got ${e}`));
    
    sequencePromises(promises);
    .as-console-wrapper {
    height : 100%;
    max-height: 100% !important;
    }

    或者,如果链中的任何承诺拒绝,您可能只想削减排序过程。然后只需删除.finally()部分,然后将sequencePromises(apis)指令插入.then()阶段。

    var simulatePromisifiedAPI = (delay,data) => new Promise((v,x) => setTimeout(_ => Math.random() > 0.1 ? v(data) : x(`error @ ${data}`), delay)),
        promises               = Array(10).fill(simulatePromisifiedAPI),
        sequencePromises       = ([api,...apis]) => apis.length ? api(250,`task no ${10-apis.length}`).then(v => (console.log(`Doing something with the API data ${v}`), sequencePromises(apis)))
                                                                                                      .catch(e => console.log(`Opps... Just got ${e}`))
                                                                : api(250,"final").then(v => console.log(`Doing something with the API data ${v}`))
                                                                                  .catch(e => console.log(`Opps... Just got ${e}`));
    
    sequencePromises(promises);
    .as-console-wrapper {
    height : 100%;
    max-height: 100% !important;
    }