Promise.all(),怎么按顺序执行?

uploadImage: function ({ files = [], name = 'file', formData = {}, header = {}, dir = '',url=config.uploadImageUrl}){
    return new es6.Promise((resolve,reject)=>{
      if (files && files instanceof Array && files.length>0){
        var promiseList=[];
        for (var i = 0; i < files.length;i++){
          promiseList[i] = new es6.Promise((resolve, reject) => {
            wx.uploadFile({
              url: url + dir, //仅为示例,非真实的接口地址
              filePath: files[i],
              name: name,
              formData: formData,
              header: header,
              success: function (res) {
                resolve(res.data);
              },
              fail: function (error) {
                reject(error);
              }
            })
          });
        }
        es6.Promise.all(promiseList)
          .then(function (result){
            resolve(result);
          })
          .then(function(error){
            reject(error);
          })
      }else{
        reject('传参有误,请传数组格式');
      }
    })
  }

选一个文件上传没有问题,选2个以上就报:

WAService.js:3 uploadFile:fail createUploadTask:fail exceed max upload connection count 1

百度了下Promise.all()的结果是按顺序输出的,但是执行是并行,问题应该在这。
无耐只好控制Promise.all()的执行顺序,执行完第一个再执行第二个。
请问Promise.all()怎么改执行顺序呢?

阅读 26.1k
6 个回答

要链式执行可以用 reduce 把 promise 串起来。

var files = [1,2,3,4,5];
var initialPromise = Promise.resolve([]);
var dealWithItem = item => new Promise((resolve, reject) => {
    setTimeout(() => resolve(item), 1000);
});

var chainedPromise = files.reduce((pre, item) => {
    return pre.then(data => {
        return dealWithItem(item)
            .then(dealedItem => {
                data.push(dealedItem);
                return data;
            });
    });
}, initialPromise);

chainedPromise.then(data => console.log(data));

Promise 太麻烦了,有了 async /await 就好多了

var files = [1,2,3,4,5];

var dealWithItem = item => new Promise((resolve, reject) => {
    setTimeout(() => resolve(item), 1000);
});

(async () => {
  try {
    var data = [];
    for(var i=0; i<files.length; i++) {
      data.push(await dealWithItem(files[i]));
    }
    console.log(data);
  } catch(e) {
    console.log(e);
  }
})()

用 async/await 写一下题主的例子:

{
  uploadImage: async function ({ files = [], name = 'file', formData = {}, header = {}, dir = '',url=config.uploadImageUrl}){
    if (files && files instanceof Array && files.length > 0) {
      let resultArr = [];
      for(var i = 0; i < files.length; i++) {
        let result = await new Promise((resolve, reject) => {
          wx.uploadFile({
            url: url + dir,
            filePath: files[i],
            name: name,
            formData: formData,
            header: header,
            success: (res) => {
              resolve(res.data);
            },
            fail: (error) => {
              reject(error);
            }
          });
        });
        resultArr.push(result)
      }
      return resultArr;
    }
    throw new Error('传参有误,请传数组格式');
  }
}

Promise.all()无法更改执行顺序。

要顺序的话,在 Promise.then 的回调里写,完成一个继续下一个这样的。

顺序和并发不可兼得

你如果有顺序执行的要求的话就不要用promise.all了,大概这样吧。

var fileList = [xxx,xxx,xxx]
function upload (fileIndex) {
 return new Promise ((res, rej)=>{
    //...
    function ajax(fileIndex) {
      //...
      success () {
        if(fileIndex>=fileList.length) {
          res()
        } else {
          ajax(++fileIndex)
        }
      },
      fail(err) {
        rej(err)
      }
    }
    ajax(0)
  }
)}
upload(0).then(xxx)

我理解这个场景是适合 Promise.all()的,但服务不支持同时上传多个文件,所以会报 exceed max upload connection count 1

可以去找服务端同学问问为啥不能同时上传
或者前端改成顺序执行,但一个一个传时间肯定更久一些

Promise.all()是并行的,等最慢的执行完后完成,你要控制顺序的话用then
不过为啥上传要顺序?直接并发传啊

新手上路,请多包涵

写个这个就行了

// Array 扩展 依次遍历
Array.prototype.inTurnForEach = function(options) {
    var _self = this
    var callback = options && options.callback ? options.callback : null
    var fail = options && options.fail ? options.fail : null
    var finish = options && options.finish ? options.finish : null
    var skipErr = options && !!options.skipErr

    var currIndex = 0
    var recursive = function() {
        if (currIndex >= _self.length) {
            typeof finish === 'function' && finish()
        } else {
            new Promise(function(resolve, reject) {
                typeof callback === 'function' && callback(_self[currIndex], currIndex, resolve, reject)
            }).then(function() {
                currIndex++
                recursive()
            }).catch(function() {
                if (skipErr) {
                    recursive()
                } else {
                    typeof fail === 'function' && fail(_self[currIndex], currIndex)
                }
            })
        }
    }
    recursive()
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题