Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/454.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript在进行多个ajax调用后保持数组顺序_Javascript_Ajax_Asynchronous_Web_Promise - Fatal编程技术网

Javascript在进行多个ajax调用后保持数组顺序

Javascript在进行多个ajax调用后保持数组顺序,javascript,ajax,asynchronous,web,promise,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 res

所以我要做的是,我有一个数组,数组中有一组表示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调用完成后结果的顺序保持不变(即results=[result from id 1,result from id 2,result from id 3,…result from id 10]?

您应该使
doAjax
返回a,将数组的每个元素映射到承诺,并将承诺数组传递给。结果数组
承诺。所有
返回的顺序与输入数组相同

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

如果你使用承诺,这是一个好主意,因为有很多原因,你会按照你创建承诺的顺序得到结果

首先,将每个AJAX调用包装在一个承诺中,并根据调用结果解决它。使用
map()
而不是
forEach()
来传播包含所有承诺的数组:

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

      resolve(returnValue);
    });
  });
});
然后,您可以做出一个单独的承诺,当数组中的所有承诺都已解决时,对此的回调将以正确的顺序传递一个包含所有结果的数组:

Promise.all(promises).then(function(promiseResults) {
  // The promiseResults array here will contain the results of all AJAX calls in the order you created them
});
如您所见,在使用承诺时,您不需要使用
计数器
或声明的
结果
变量。

这一切都可以写得更简洁、更高效,但我的示例有望帮助您理解这一点。

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

var ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function(id) {
  return {id: id};
});
id.result = returnValue;
现在,不要在
doAjax
中引用id,而是使用
id.id
。 您可以简单地向
id
对象添加新属性,而不是将结果推送到单独的数组中,如下所示:

var ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function(id) {
  return {id: id};
});
id.result = returnValue;
如果愿意,可以执行另一个映射操作来创建
结果
数组:

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

forEach
方法接受一个回调,该回调将项的索引作为第二个参数。因此,可以将结果与创建它的id放在同一个索引中?即:
ids.forEach(函数(id,index){results[index]=returnValue})
。在当前执行上下文完成且JS运行时空闲之前,无法使用AJAX调用结果。这意味着当成功回调运行时,循环将完成。您应该将第二个参数添加到
中,然后
,以便在其中一个请求失败的情况下也可以执行一些操作。