这些年整理的Promise核心知识点和重要应用场景

3个实例方法

Promise.prototype.then()

js 复制代码
const promise1 = new Promise((resolve, reject) => {
  resolve('Success!');
});

promise1.then((value) => {
  console.log(value);
  // Expected output: "Success!"
});

Promise.prototype.catch()

js 复制代码
const promise1 = new Promise((resolve, reject) => {
  throw new Error('Uh-oh!');
});

promise1.catch((error) => {
  console.error(error);
});
// Expected output: Error: Uh-oh!

Promise.prototype.finally()

js 复制代码
function checkMail() {
  return new Promise((resolve, reject) => {
    if (Math.random() > 0.5) {
      resolve('Mail has arrived');
    } else {
      reject(new Error('Failed to arrive'));
    }
  });
}

checkMail()
  .then((mail) => {
    console.log(mail);
  })
  .catch((err) => {
    console.error(err);
  })
  .finally(() => {
    console.log('Experiment completed');
  });

6个静态方法

Promise.all()

js 复制代码
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// Expected output: Array [3, 42, "foo"]

Promise.allSettled()

js 复制代码
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];

Promise.allSettled(promises).then((results) => results.forEach((result) => console.log(result.status)));

// Expected output:
// "fulfilled"
// "rejected"

Promise.any()

js 复制代码
const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'quick'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, 'slow'));

const promises = [promise1, promise2, promise3];

Promise.any(promises).then((value) => console.log(value));

// Expected output: "quick"

Promise.race()

js 复制代码
const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// Expected output: "two"

Promise.reject()

js 复制代码
function resolved(result) {
  console.log('Resolved');
}

function rejected(result) {
  console.error(result);
}

Promise.reject(new Error('fail')).then(resolved, rejected);
// Expected output: Error: fail

Promise.resolve()

js 复制代码
const promise1 = Promise.resolve(123);

promise1.then((value) => {
  console.log(value);
  // Expected output: 123
});

Promise穿透

"Promise穿透"是指在Promise链中,如果在then或catch的处理函数中返回的不是一个新的Promise,那么下一个then或catch会接收到上一个then或catch返回的值

js 复制代码
Promise.resolve(1) .then(() => { 
// 这里没有返回新的Promise,也没有返回值,所以状态会被穿透到下一个then 
}) .then(value => { 
// 输出undefined,因为状态被穿透了 
  console.log(value) 
})
js 复制代码
var myselflog=function(a){ 
console.log("myselflog:"+a); 
} 
Promise.resolve(1)
.then(2) 
.then(Promise.resolve(3)) 
.then(myselflog);
// 输出myselflog:1

手动实现allSettled

allSettled是最近才有的,为了兼容性有时需要自定义实现

js 复制代码
    // allSettled是即使错误了也都返回一步的promise
    // 思路是让 Promise.all 入参中的所有 promise 都映射为新的最终状态为 fulfilled 的 promise
    // 也可以通过逐个遍历的方式实现
    Promise.allSettled = function (promises) {
        return Promise.all(
          promises.map((p) =>
            Promise.resolve(p).then(
              (res) => {
                return {
                  status: 'fulfilled',
                  value: res
                }
              },
              (error) => {
                return {
                  status: 'rejected',
                  reason: error
                }
              }
            )
          )
        )
      }

终止Promise向下执行

js 复制代码
Promise.resolve() 
.then(() => { 
  console.log('Step 1'); 
  return new Promise(() => {}); 
})
.then(() => { 
  console.log('Step 2'); 
  // 这里不会被执行 
})

在这个例子中,第一个then方法中返回了一个新的Promise,这个Promise永远不会被resolve或reject,所以第二个then方法不会被执行。 然而,这种方法并不是真正意义上的"终止"Promise,因为新的Promise仍然在运行,只是它永远不会被settled,所以后续的then方法不会被执行。这可能会导致内存泄漏等问题,所以在实际开发中需要谨慎使用。

Sleep函数

js 复制代码
const wait = (ms) => new Promise((resolve)=> setTimeout(resolve, ms)) 
const asyncFn = async () => { 
   await wait(1000) 
   console.log('等待异步函数执行结束') 
} 

asyncFn()

Promise串行

js 复制代码
class PromiseChunk {
    constructor () {
      this.maxCount = 3
      this.curCount = 0
      this.parr = []
    }

    addPromise (p) {
      this.parr.push(p)
    }

    start () {
      for (let i = 0; i < this.maxCount; i++) {
        this.executePromise(this.parr[i])
      }
    }

    executePromise () {
      if (this.curCount >= this.maxCount || this.parr.length === 0) {
        return false
      }
      this.curCount++
      const p = this.parr.shift()
      p.then((res) => {
        console.log(res, '33333333')
        this.curCount--
        this.executePromise()
      })
    }
  }

  const pc = new PromiseChunk()
  const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1)
    }, 1000)
  })
  const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(2)
    }, 2000)
  })
  const p3 = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(3)
    }, 3000)
  })
  pc.addPromise(p1)
  pc.addPromise(p2)
  pc.addPromise(p3)
  pc.start()

Promise并行

可以直接使用Promise.all()实现

js 复制代码
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// Expected output: Array [3, 42, "foo"]

myPromise

从一道让我失眠的 Promise 面试题开始,深入分析 Promise 实现细节

重要场景

字节跳动面试官:请你实现一个大文件上传和断点续传

JavaScript 中如何实现大文件并行下载?

参考文献

mozilla开发者社区

相关推荐
轻口味33 分钟前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami35 分钟前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
吃杠碰小鸡1 小时前
lodash常用函数
前端·javascript
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼1 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
m0_748250031 小时前
Web 第一次作业 初探html 使用VSCode工具开发
前端·html
一个处女座的程序猿O(∩_∩)O2 小时前
vue3 如何使用 mounted
前端·javascript·vue.js
m0_748235952 小时前
web复习(三)
前端
AiFlutter2 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
麦兜*2 小时前
轮播图带详情插件、uniApp插件
前端·javascript·uni-app·vue