Promise实战

Promise 实现串行

要求: 有一组异步请求 apis = [ url1, url2, url3, ...], 用Promise的方式实现串行调用。

这个场景和tapable的 异步串行 类似,使用方式就是p.then().then()..., 核心是在thenable里面返回一个新的promise,这样就能一直执行。

const p = Promise.resolve();
apis.forEach(api => {
    p = p.then(fetch(api));
});

p.then(res1).then(res2)...

通过reduce实现

const p = apis.reduce((promise,api) => promise.then(fetch(api)),Promise.resolve())

Promise 并发缓存

场景:现有一批相同的并发查询请求,希望只查询一次SQL,期间的请求走缓存,使用promise怎么实现。

const sqlResult = 'sql result';
let cacheDate = '';
let cachePromise = null;
function SQL() {
  if (cacheDate) return cacheDate;
  if (cachePromise) return cachePromise;
  cachePromise = new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('只执行一次');
      resolve(sqlResult);
      cacheDate = sqlResult;
      cachePromise = null;
    }, 1000);
  });

  return cachePromise;
}

for (let i = 0; i < 10; i++) {
  SQL().then((res) => {
    console.log(res);
  });
}

promise 并发排队

场景:有多个图片资源的url,已经存储在数组urls中,而且已经有一个函数loadImg,输入一个url链接,返回一个 Promise,该Promise在图片下载完成的时候resolve,下载失败则reject。任意时刻,同时下载的链接数量不可以超过3个,使用最快的速度将图片下载完毕。

实现如下, 关键点在于使用了Promise.race()检测哪一个最先执行完,执行完返回一个promise,使用链式调用将剩下的串起来

因此,基于这种场景(排队并发),我们可以设计一个通用的方法。参考

Promise 错误捕获

下面这段代码会如何输出:

resolve之后,promise的状态已经结束了,因为错误在setTimeout,属于下一次的事件循环,所以这里会被抛出,不会被promise吃掉。因此输出结果是

Promise的微任务

参考

Last updated