从微信小程序看promsie.all和promise顺序执行

1、前言

最近在作小程序的开发,碰到的一个需求就是表单提交,提交的表单中包含有图片,微信这边的作法是先上传图片,后台把图片名称和地址返回给你,而后你把图片信息插入到表单的相应位置再提交表单,这里就涉及到如何上传完图片的请求再上传表单,并且微信小程序里面若是图片是多个的话,也只能一张张上传。简单来讲就是上传完图片(多个请求),拿到返回值,再上传表单,该如何作?前端

2、Promise.all和Promise.race

先来介绍Promise.all和Promise.race方法的不一样点

Promise.all(iterable) 方法指当全部在可迭代参数中的 promises 已完成,或者第一个传递的 promise(指 reject)失败时,返回 promise。iterable为可迭代对象,可是通常为数组。返回值也是一个Promise对象。
须要明确的几点,Promise.all是并发执行的同时运行多个Promise对象,并且返回的Promise对象的参数是一个数组,数组中的各项也是可迭代对象执行的顺序返回vue

Promise.race(iterable) 方法返回一个新的 promise,参数iterable中只要有一个promise对象”完成(resolve)”或”失败(reject)”,新的promise就会马上”完成(resolve)”或者”失败(reject)”,并得到以前那个promise对象的返回值或者错误缘由。因此只要iterable中有一个完成或者失败就当即返回一个promise对象。根据race这个单词为赛跑也能得出,最早到达的当即返回一个promise对象。npm

根据上面的定义,咱们采用的Promise.all方法来完成咱们的需求。小程序

//存储promise对象的数组
let promiseArr = [];
//图片地址数组
let imageList = [];
//将图片地址的上传的promise对象加入到promiseArr
for (let i = 0; i < imageList.length; i++) {
    let promise = new Promise((resolve, reject) => {
        //微信图片上传
        wx.uploadFile({
            url: 'https://xxx.xxx.xxx/api/uploadImage',
            filePath: imageList[i],
            name: 'file',
            success: function(res) {
                //能够对res进行处理,而后resolve返回
                resolve(res);
            },
            fail: function (error) {
                reject(error);
            },
            complete: function (res) {
            },
        })
    });
    promiseArr.push(promise)
}
//Promise.all处理promiseArr数组中的每个promise对象
Promise.all(promiseArr).then((result) => {
    //对返回的result数组进行处理
})
复制代码

3、微信小程序的问题

在作微信小程序的图片上传功能,这边只能先上传图片,而后将图片名和地址以response返回。微信小程序

这里面咱们就是用了promise.all方法可是有一个问题就是,promise.all是并发执行的,可是微信小程序一次只能并发10个请求。api

对于图片上传,可能须要一次上传超过10张图片,也就是一次并发超过10个请求,这样的话微信就会报错数组

“WAService.js:4 uploadFile:fail createUploadTask:fail exceed max upload connection count 10”


4、顺序Promise执行处理

由于Promise.all是同时运行多个promsie对象,因此对于这种并发的数量,小程序是有限制的,一次只能并发10个,因此若是想突破这种限制,能够进行顺序执行每一个Promise。
代码以下:promise

//顺序处理函数
function sequenceTasks(tasks) {
    //记录返回值
    function recordValue(results, value) {
        results.push(value);
        return results;
    }
    let pushValue = recordValue.bind(null, []);
    let promise = Promise.resolve();
    // 处理tasks数组中的每一个函数对象
    for (let i = 0; i < tasks.length; i++) {
        let task = tasks[i];
        promise = promise.then(task).then(pushValue);
    }
    return promise;
}

//函数数组,每一个函数的返回值是一个promise对象
let promiseFuncArr = [];
//图片地址数组
let imageList = [];
//将图片地址的上传的函数加入到promiseFuncArr数组中
for (let i = 0; i < imageList.length; i++) {
    let promiseTemp = function(){
        return new Promise((resolve, reject) => {
            //微信图片上传
            wx.uploadFile({
                url: 'https://xxx.xxx.xxx/api/uploadImage',
                filePath: imageList[i],
                name: 'file',
                success: function(res) {
                    //能够对res进行处理,而后resolve返回
                    resolve(res);
                },
                fail: function (error) {
                    reject(error);
                },
                complete: function (res) {
                },
            })
        });
    };
    promiseFuncArr.push(promiseTemp)
}

sequenceTasks(promiseFuncArr).then((result) => {
    //对返回的result数组进行处理
});
复制代码

1.这里解释一下sequenceTasks函数的做用

首先recordValue函数传入两个值,一个是results是返回的数组,另外一个是value,value是传入的值,results.push(value);将每个值push到results数组,而后再返回results数组。bash

let pushValue = recordValue.bind(null, []);
pushValue也是一个函数对象,将recordValue bind到一个[ ]数组中,第一个参数传null表明,不改变函数this的指向,因此pushValue获得就是一个function (value)的函数,参数传入value。微信

promise = promise.then(task).then(pushValue);
task是函数,函数返回promise对象,在咱们这里就是上传图片函数,每一张图片上传都建立一个函数,then(pushValue),pushValue是function (value)的函数,value表明的就是图片上传以后的返回值,pushValue将返回值push到result数组中,依次执行,依次加入到result数组中,最后返回。就能够获得一个对象数组,数组中就是依次执行返回的结果。

2. sequenceTasks也里面的for循环,也能够写成以下的reduce方式:

function sequenceTasks(tasks) {
    //记录返回值
    function recordValue(results, value) {
        results.push(value);
        return results;
    }
    let pushValue = recordValue.bind(null, []);
    return tasks.reduce(function (promise, task) {
        return promise.then(task).then(pushValue);
    }, Promise.resolve());
}
复制代码

(来自公众号:前端八点半)

相关文章
相关标签/搜索