Javascript在进行多次ajax调用后维护数组顺序

时间:2017-10-23 18:04:10

标签: javascript ajax asynchronous web promise

所以我要做的是我有一个带有一堆整数的数组,它代表一个id。我用id循环遍历数组。对于每个id,我进行一个ajax调用,它返回给我一个json然后我将这个json追加到我的结果数组中。我想保持结果数组的顺序与我进行ajax调用的顺序相同(即如果我按顺序'/ url / 1','url / 2',url / 3'对ID进行GET调用,我希望结果数组按照调用的顺序存储id 1,2和3的结果。这是我必须显示的内容的通用代码。

var ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var results = [];
var counter = 1;
ids.forEach(function(id) {
    doAjax('GET', 'url' + id, function(returnValue) {



        results.push(returnValue);
        if (counter == 10) {
            //dispatch some event
        }

    });



});

问题是结果数组的顺序每次都不同,因为ajax调用的异步性质。在有所有ajax调用之后,有什么方法可以确保结果的顺序保持不变(即结果= [来自id 1的结果,来自id 2的结果,来自id 3的结果,...来自id 10的结果) ]

3 个答案:

答案 0 :(得分:2)

你应该让doAjax返回promise,将数组的每个元素映射到一个promise并将promises数组传递给Promise.all。结果数组Promise.all“返回”与输入数组的顺序相同。

Promise.all(ids.map(id => doAjax('GET', 'url' + id)).then(results => {
    //dispatch some event
});

答案 1 :(得分:1)

如果您使用promises,这是一个好主意,出于多种原因,您将按照创建它们的顺序获得结果。

首先将每个AJAX调用包装在一个promise中,然后使用调用结果解析它。使用map()代替forEach()来传播包含所有承诺的数组:

var promises = ids.map(function(id) {
  return new Promise(function(resolve) {
    doAjax('GET', 'url' + id, function(returnValue) {

      resolve(returnValue);
    });
  });
});

然后你可以制作一个单一的promise,当数组中的所有promise都已解析时解析,对此的回调将传递一个数组,其中所有结果都按正确的顺序排列:

Promise.all(promises).then(function(promiseResults) {
  // The promiseResults array here will contain the results of all AJAX calls in the order you created them
});

正如您所看到的,在使用承诺时,您不需要counter或声明的results变量。
这些都可以更加整齐有效地编写,但我的例子有望帮助你理解。

答案 2 :(得分:0)

你应该让每个id都是这样的对象:

var ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function(id) {
  return {id: id};
});

现在,不要在doAjax中引用ID,而是使用id.id。 您可以简单地将新属性添加到id对象,而不是将结果推送到单独的数组中,如下所示:

id.result = returnValue;

如果您愿意,可以执行另一个地图操作来创建results数组:

var results = ids.map(function(id) {
  return id.result;
});