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

问题描述 投票:1回答:3

我一直在尝试的是按顺序处理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调用应该等到前一个调用完成。)

你看到我做错了吗?

任何建议将被认真考虑。

javascript promise bluebird
3个回答
1
投票

好的,如果Restangular.one()返回一个promise(你的注释现在指出)并且你想要顺序处理这些api调用(一个接一个),那么你只需要正确地组织Bluebird的.mapSeries()的参数。它需要一组数据和一个函数(对该数据进行操作并返回一个promise)。

那么,让我们以这种方式组织你的东西:

const data = [
    {endPoint: "http://somedomain.com/api/blahblah", args: [1,2]},
    {endPoint: "http://somedomain.com/api/another/api", args: ["a", "b"]},
    {endPoint: "http://somedomain.com/api/yetanother", args: ["abc"]},
];

Promise.mapSeries(data, function(dataObj) {
    return Restangular.one(dataObj.endPoint, ...dataObj.args);
}).then(results => {
    // array of results here
    console.log(results);
}).catch(err => {
    // error occurred here
    console.log(err);
});

既然你说Restangular.one()已经返回一个承诺,我没有看到任何理由你需要将它包装在你的resolveApi()函数中。这是不需要的,我们当然不需要将承诺转变成使用.mapSeries()的简单回调。


您的实现中缺少许多东西,但主要的是您立即调用所有异步操作,然后尝试管理promise。这不会对您的操作进行排序。它将所有这些并行运行。此外,如果你给.mapSeries()一个承诺数组,它不能对操作进行排序,因为它们都已经启动了。为了让它在异步操作启动时进行管理,以便它可以对它们进行排序,你必须向它传递一个数据数组和一个调用函数,该函数传递一个该数据项并返回一个promise。然后,它可以一次调用一个,您的操作将一次启动一个。


1
投票

qazxsw poi不是真正的承诺,它将立即解决qazxsw poi

我想你想在ajax成功之后解决,resolveApi(Restangular.one("api/blahblah",{/*input data*/}))并行运行这是最快的方法,像这样:

callback

或顺序

Promise.all

而且,你可能想在下一个ajax中使用一个ajax的结果,你可以使用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) => {

})

0
投票

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

  1. 如果抛出任何错误,这个将处理错误并继续下一个承诺。我使用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)
})
.finally()

或者,如果链中的任何承诺拒绝,您可能只想削减排序过程。然后只需删除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()
© www.soinside.com 2019 - 2024. All rights reserved.