用promise.all解决ajax异步循环请求问题

var promises = [1, 2].map(function(id) {
    return id;
});
Promise.all(promises).then(function(val) {
    $.ajax() {
        data: 一次为数组里面的值
    }
}).catch(function(reason) {
    // ...
});
阅读 9.9k
3 个回答

你可以看下 这里的 解释
http://es6.ruanyifeng.com/#do...

-----补充

var promises = [1,2,3].map(function (id) {
  return setTimeout(()=>{console.log(id)},1000);
});

Promise.all(promises).then(function (posts) {
  console.log('all r')
}).catch(function(reason){
  
});
// 输出 'all r', 1, 2, 3 

ajax 的循环依赖调用可以这么写,接住异步函数


function ajax1 () {
  return new Promise(function (resolve, reject){
    console.log("执行:ajax1,执行2s")
    setTimeout(()=>{resolve('ajax1');},2000);
  });
}
function ajax2 () {
  return new Promise(function (resolve, reject){
    console.log("执行:ajax2,执行1s")
    setTimeout(()=>{resolve('ajax2');},1000);
  });
}
function ajax3 () {
  return new Promise(function (resolve, reject){
    console.log("执行:ajax3,执行3s")
    setTimeout(()=>{resolve('ajax3');},3000);
  });
}

function run (req) {
   var it = generator(req); ;
    function* generator(arr=[]) {
      try {
          for(let i of arr){
            yield i();
        }

      } catch (e) {
        console.log(e);
      }
    };

  function go(result) {
    if (result.done){
      console.log('结束')
      return result.value;
    }
        
    return result.value.then(function (value) {
      return go(it.next());
    }, function (error) {
      return go(it.throw(error));
    });
  }

  go(it.next());
}

run([ajax1,ajax2,ajax3]);

Promise.all() 并不能解决循环的问题,一般情况下 .all() 的参数是 Promise 数组(暂时不考虑其它类似)。那么,数组中的每个 Promise 都代表着一个异步操作,Promise.all() 的作用是等待这些异步操作全部执行完成,所以实质上并不是 Promise.all() 是并发的,而是 Promise.all() 等待着一堆并发执行完成。

因此,Promise.all() 并不能解决有序循环。作为特例,如果 Promise.all() 等待的全都是同步代码,比如题主示例中虽然用了 .map(),映射结果却并不是 Promise 对象,而是同步执行(直接返回的 id),这种情况下,实际是依次执行的完了再把结果放入 .all() 的,所以是同步顺序循环处理的(就是 map 干的事情)。题主的第一段代码,如果变量名不是 promises,你觉得它跟异步或者 Promise 有任何关系吗

然后当然要指出 ajax 调用时候的一个失误:{} 中的内容应该是 ajax 的参数,所以应该放在括号中 ({...}) 才对。

由于 promises 变量保存的只是一个同步运行的结果集,所以 Promise.all(promises) 其实就是对 then() 的回调直接传递的这个结果集,所以 val 的值实际就是 [1, 2]。因此下面这个写法是没有问题的

$.ajax({
    data: val
});

问题在于下面这里

Promise.all(promises)
    .then(function(val) {
        // 问题在把 ajax 放入 then 回调中之后
        $.ajax({
            data: val
        });
    })
    .catch(function(err) {
        // ....
    });

这里如果 ajax 发生错误,它不会抛异常,而是等待它自己的 .fail() 处理,因为没有定义,所以就被丢弃了。它并不会传递到后面的 .catch() 中,要解决这个问题,可以是得用 ajax 自己的 .fail() 来处理错误

Promise.all(promises)
    .then(function(val) {
        // 问题在把 ajax 放入 then 回调中之后
        $.ajax({ data: val })
            .fail(function(err) {
                // 这里处理错误逻辑
            });
    });

也可以是,直接将 ajax 的结果(thenable)传递下去,由 Promise 机制的 .catch() 来处理

Promise.all(promises)
    .then(function(val) {
        // 问题在把 ajax 放入 then 回调中之后
        return $.ajax({ data: val });
    })
    .catch(function(err) {
        // 处理错误逻辑
    });
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题