使用Promise.all()实现多异步任务等待

背景:最近公司使用的图形验证码开始打起了广告,于是组内想着找个开源项目去加工一下,改造过程中遇到一个问题,开源项目的坐标是由前端随机生成的,不是很安全,改造成服务端生成的话,图形验证码的生成就有两个异步请求,一个是图片的加载,一个是服务端请求坐标,那么最好的就是两个异步请求同时发起,等待两个异步请求任务都完成之后再进行之后的业务逻辑。

一、简单梳理一下

其实问题用一句话描述就是“同时开始两个异步任务,两个异步任务完成之后执行后面的逻辑”,那么很自然的就想到了Promise.all()这个方法,但这里有一个问题就是图片的加载并不是一个Promise,我们有的只有onload和onerror这些回调接口,那么问题就变成了怎么让onload的时候resolve Promise。

二、在Promise构造函数外resolve Promise

经过上面的分析问题就变成了在Promise构造函数之外resolve Promise,大致思路有两种:
1. 将resolve和reject存起来,在需要的时候调用;
2. 在构造函数中设定onload和onerror回调事件;
第一种思路比较简单,但将resolve和reject暴露出去之后难以维护;第二种就要好一点,下面看看怎么实现吧。

// 这里用一个函数来封装一下onload和onerror的回调函数,在Promise里把resolve作为钩子函数传进去,这样可以把业务逻辑写在一起,比如可以在error中实现尝试重新获取或者读取本地图片
const loadHandle = function (hook) {
    return () => {
        if (hook && typeof hook === 'function') {
            hook();
     }
        // 业务逻辑...
  }
};
const errorHandle = function (hook) {
  return () => {
    if (hook && typeof hook === 'function') {
      hook();
    }
        // 业务逻辑...
  }
};
const src = '';
const img = new Image();
// 加载图片的Promise
const imgLoadPromise = new Promise((resolve, reject) => {
    img.src = src;
    img.onload = loadHandle(resolve);
    img.onerror = errorHandle(reject);
});
// 获取坐标
const coordinatesPromise = new Promise((resovle, reject) => {
    $.ajax({
   type: "get",
   async: true,
   url: 'url',
   data: "",
   success: res => {
     resovle(res);
   },
   error: err => {
        reject(err);
   }
    })
});
Promise.all([imgLoadPromise, coordinatesPromise]).then((res) => { // res是Promise数组的resolve的结果
    // 处理逻辑...
}).catch((err) => { // 一旦Promise数组中有一个reject了就会将这条错误结果给到失败状态的回调函数
    // 错误处理...
})

你可能感兴趣的:(使用Promise.all()实现多异步任务等待)