Promise,async,await 知识点

1,Promise A+规范

1,所有的异步场景,都应该看做是一个异步任务

在 js 中表现为一个对象——Promise 对象。也就是任务对象。

2,Promise 对象有2个阶段,3个状态

在这里插入图片描述
1,任务创建

  • 任务总是从未决阶段 --> 已决阶段,无法逆行。
  • 任务总是从挂起状态 --> 完成或失败状态,无法逆行。
  • 任务一开始都是 pending 状态,任务一旦完成或失败,状态不能再被改变
const result = new Promise((resolve, reject) => {
    
    
  resolve(1);
  reject(2); // 无效
  resolve(3); // 无效
  console.log(123); // 正常执行
});
console.log(result); // Promise {<fulfilled>: 1}

2,更改状态

  • pending --> fulfilled 称为 resolve(data)
  • pending --> rejected 称为 reject(reason)

3,后续处理

  • fulfilled 的后续处理,称为 onFulfilled
  • rejected 的后续处理,称为 onRejected

在这里插入图片描述

2,Promise 简单API

1,创建任务

const pro = new Promise(() => {
    
    
  console.log('会被立即执行的函数');
})
console.log(pro) // Promise { <pending> }

2,更改状态

const pro = new Promise((resolve, reject) => {
    
    
  console.log('会被立即执行的函数')
  setTimeout(() => {
    
    
    if (Math.random() < 0.5) {
    
    
      resolve('成功') // 从 pending 状态 --> fulfilled 状态
    } else {
    
    
      reject('失败') // 从 pending 状态 --> rejected 状态
    }
  }, 1000);
})

3,后续处理

pro.then(
  // fulfilled 的回调函数
  (data) => {
    
    
    console.log(data)
  },
  // rejected 的回调函数
  (reason) => {
    
    
    console.log(reason)
  }
)

实践举例:delay 延迟工具函数

function delay(duration) {
    
    
  return new Promise((resolve) => {
    
    
    setTimeout(() => {
    
    
      resolve();
    }, duration);
  });
}

await delay(3000)

3,链式调用

在这里插入图片描述
通过 then()catch() 函数做后续处理。

promise.then(
  // fulfilled 的回调函数
  (data) => {
    
    
    console.log(data)
  },
  // rejected 的回调函数
  (reason) => {
    
    
    console.log(reason)
  }
)

// 相当于
promise
  .then(
    // fulfilled 的回调函数
    (data) => {
    
    
      console.log(data);
    }
  )
  .catch(
    // rejected 的回调函数
    (reason) => {
    
    
      console.log(reason);
    }
  );

常见写法:

/*
 * 任务成功后,执行处理1,失败则执行处理2
 */
promise.then(处理1).catch(处理2)

/*
 * 任务成功后,依次执行处理1、处理2,若 promise 任务失败 或 处理1和2有错,都会执行处理3
 */
promise.then(处理1).then(处理2).catch(处理3)

特性:

3.1,then()必定返回一个新 Promise 对象(新任务)。

根据上面的等效写法,catch() 也会返回一个新 Promise 对象(新任务)。

3.2,新任务的状态,取决于前任务的后续处理。

  • 若没有相关的后续处理,新任务的状态和前任务一致,数据为前任务的数据。

换句话说,不相关的后续处理函数不会执行。

下面的例子中,因为 Promise 一开始的状态时 pendingsetTimeout 为了获取最终状态。
至于 setTimeout 为什么可以获取,参考事件循环机制

举例1,promise1fulfilled 状态,但却没有 then() 做对应的后续处理。

const promise1 = new Promise((resolve) => {
    
    
  resolve(1);
});
const promise2 = promise1.catch(() => {
    
    
  console.log("不会被打印");
});

setTimeout(() => {
    
    
  console.log(promise2); // Promise {<fulfilled>: 1}
});

举例2,promise1rejected 状态,但却没有 catch() 做对应的后续处理。

const promise1 = new Promise((resolve, reject) => {
    
    
  reject(1);
});
const promise2 = promise1.then(() => {
    
    
  console.log("不会被打印");
});

setTimeout(() => {
    
    
  console.log(promise2); // Promise {<rejected>: 1}
});
  • 若有后续处理但还未执行,新任务挂起
const promise1 = new Promise((resolve) => {
    
    
  console.log(1);
  setTimeout(() => {
    
    
    resolve();
  }, 1000);
});
const promise2 = promise1.then(() => {
    
    
  console.log(2);
});

setTimeout(() => {
    
    
  console.log(promise2);
});

// 1
// Promise {<pending>}
// 2
  • 若后续处理执行了,则根据后续处理的情况确定新任务的状态:
    • 后续处理执行无错,新任务的状态为完成,数据为后续处理的返回值(没有返回,就是 undefined)
    • 后续处理执行有错,新任务的状态为失败,数据为异常对象
    • 后续执行后返回的是一个任务对象,新任务的状态和数据与该任务对象一致

第1种情况举例:

const promise1 = new Promise((resolve) => {
    
    
  resolve();
});
const promise2 = promise1.then(() => {
    
    
  return 123;
});

setTimeout(() => {
    
    
  console.log(promise2); // Promise {<fulfilled>: 123}
});
const promise1 = new Promise((resolve, reject) => {
    
    
  reject();
});
const promise2 = promise1.catch(() => {
    
    
  return 123;
});

setTimeout(() => {
    
    
  console.log(promise2); // Promise {<fulfilled>: 123}
});

第2种情况举例,catch 同理。

const promise1 = new Promise((resolve) => {
    
    
  resolve();
});
const promise2 = promise1.then(() => {
    
    
  throw "一个错误";
});

setTimeout(() => {
    
    
  console.log(promise2); // Promise {<rejected>: '一个错误'}
});

第3种情况举例,

const promise1 = new Promise((resolve) => {
    
    
  resolve();
});
const promise2 = promise1.then(() => {
    
    
  // promise2 的状态取决于这个 Promise 对象的状态
  return new Promise((resolve, reject) => {
    
    
    resolve(1);
  });
});

setTimeout(() => {
    
    
  console.log(promise2); // Promise {<fulfilled>: 1}
});

一道面试题

const result = new Promise((resolve) => {
    
    
  resolve(1);
})
  .then((res) => {
    
    
    console.log(res); // 1
    return new Error(2); // 注意,这不是报错,而是一个对象
  })
  // 不执行
  .catch((err) => {
    
    
    throw err;
  })
  // 对上一个 then 返回的 Promise 做了处理,但没有返回结果。
  .then((res) => {
    
    
    console.log(res);
  });

setTimeout(() => {
    
    
  console.log(result); // Promise {<fulfilled>: undefined}
});

3,Promise 静态方法

任务即 Promise 对象

静态方法 作用
Promise.resolve() 直接返回 fulfilled 状态的任务
Promise.reject() 直接返回 rejected 状态的任务
Promise.all(任务数组) 返回一个数组
任务全部成功则成功
任何一个失败则失败
Promise.any(任务数组) 返回一个任务
任何一个成功则成功
任务全部失败则失败,并返回一个数组
Promise.race(任务数组) 返回一个任务
只要有一个进入已决状态,则已决,状态和其一致
Promise.allSettled(任务数组) 返回一个数组
任务数组全部已决则成功
该任务不会失败

主要介绍下 Promise.allSettled(任务数组)

1,当任务数组都变为已决状态,则返回每个任务的结果。

Promise.allSettled([
  Promise.resolve(1),
  Promise.reject(2),
  new Promise((resolve) => {
    
    
    resolve(3)
  })
]).then((values) => {
    
    
  console.log(values);
});

结果:
在这里插入图片描述

2,当任务数组中有一个未决,则永远处于 pending 状态。

Promise.allSettled([
  Promise.resolve(1),
  Promise.reject(2),
  new Promise(() => {
    
    })
]).then((values) => {
    
    
  console.log(values); // then() 永远不被执行
});

实用举例:需要获取所有的请求结果,有失败的请求没有关系,最后能获取所有成功的数据即可。

// 模拟请求
function getData(pageIndex) {
    
    
  return new Promise((resolve, reject) => {
    
    
    if (Math.random() < 0.4) {
    
    
      reject("网络错误");
    }

    setTimeout(() => {
    
    
      resolve(pageIndex);
    }, Math.floor(Math.random() * 3000));
  });
}

const arr = [];
for (let i = 0; i < 5; i++) {
    
    
  arr.push(getData(i));
}

Promise.allSettled(arr).then((values) => {
    
    
  console.log(values);
});

结果
在这里插入图片描述

4,async 和 await

async

1,async 关键字用于修饰函数,被它修饰的函数,一定返回 Promise 对象。

async function fun() {
    
    }
console.log(fun()) // Promise {<fulfilled>: undefined}

async function fun2() {
    
    
  await 1
}
console.log(fun2()) // Promise {<pending>}。因为有异步代码

2,若执行过程报错,则任务是 rejected

async function fun() {
    
    
  throw new Error(1);
}
console.log(fun()); // Promise {<rejected>: Error: 1

3,当 async 修饰的函数中明确返回了 Promise 对象,则该函数相当于没有被 async 修饰。

async function fun() {
    
    
  return new Promise((resolve) => {
    
    
    resolve(1);
  });
}

await

1,await 用于等待一个 Promise 对象已决后,获取已决后的结果,如果结果为 rejected 状态,则抛出异常,可以用 try...catch 捕获。

async function fun() {
    
    
  try {
    
    
    await Promise.reject(1);
  } catch (error) {
    
    
    console.log('error:' + error);
  }
}
fun() // error:1

2,因为 await 需要放到异步函数中,所以可以用立即执行函数。

(async ()=> {
    
    
  await delay(1000)
  console.log('等待1s后执行后续操作');
})()

3,当 await 后的表达式的值不是 Promise,await 会把该值转换为 fulfilled 状态的 Promise,然后返回其结果。

await 1 //相当于 await Promise.resolve(1)

5,面试题

面试题


以上。

猜你喜欢

转载自blog.csdn.net/qq_40147756/article/details/132711878