一篇文章解决你的Promise, async, await面试焦虑

本文详细介绍了Promise和async/await的相关知识,包括Promise的作用、状态、值及其方法,阐述了如何解决回调地狱问题。此外,文章还深入探讨了async函数和await表达式的用法,以及它们在处理异步操作时的注意事项和异常处理。手写Promise.all和Promise.race的部分,帮助读者更好地理解和应用这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Promise

Promise是一个构造函数,可以进行对象的实例化,多用于处理> 异步任务(AJAX,文件IO,setTimeout)

Promise的作用

  • Promise支持链式调用,可以解决回调地狱的问题
  • 指定回调函数的方式更加灵活
const p = new Promise((resolve, reject) => {
  let a;
  if (a < 30) {
    resolve("OK");
  } else {
    reject("Error");
  }
});
p.then(
  (value) => {
    console.log(value);
  },
  (error) => {
    console.warn(error);
  }
);

**注意:**Promise定义时内部的函数是同步调用的,即立即执行(里面放着异步函数仍然是异步)

Promise对象的状态

是Promise实例对象的一个属性 PromiseState

  • pending
  • resolved / fulfilled的Promise
  • rejected
    **注意:**Promise对象的状态只能改变一次

Promise对象的值

是Promise实例对象的另一个属性 PromiseResult,他保存着对象成功/失败的结果

Promise对象的几种方法

Promise.prototype.then 进行异步调用,处理上一个Promise结果
Promise.prototype.catchthen类似,但只能进行失败的回调

Promise原型的几种方法

Promise.resolve()

  • 如果传入的参数为非Promise类型的对象,则返回的结果为成功的Promise对象,且返回对象的值为该参数。
  • 如果传入的参数为Promise对象,则参数对象的结果决定了resolve的结果。

Promise.reject()

  • 与resolve同理

Promise.all(promises)

  • 返回一个Promise对象
  • 传入一个包含n个promise对象的数组
  • 传入的数组中所有Promise都成功才成功,有一个失败就直接失败

Promise.race(promises)

  • 返回一个Promise对象
  • 该方法由数组中第一个改变状态的Promise对象决定,他为fulfilled,返回的对象状态就是fulfilled;它为rejected,返回的对象撞他就是rejected

改变Promise对象状态的3种方式

1. resolve函数
2. reject函数
3. throw抛出错误    `throw '错误'`

注意: 当Promise对象改变后,对应的回调函数都会执行

执行then方法后返回的Promise对象的状态

1. 抛出错误 => rejected
2. 返回结果是一个非Promise对象
    return 521;   =>  fulfilled
3. 返回的是一个Promise对象 => 取决于该Promise的状态

Promise的异常穿透

可以在整个then的链条最后捕获错误

p.then(v=>{}).then(v=>{}).then(v=>{})
.catch()

中断Promise的链式调用

  • 只有一种方式:
    返回一个pending状态的Promise对象,状态不改变自然不会往下运行
return new Promise(()=>{});

手写Promise.all

/**
 * Promise.all的封装
 * @param {Promise []} promises
 * @returns
 */
Promise.all = function (promises) {
  return new Promise((resolve, reject) => {
    let count = 0;
    let arr = [];
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(
        (v) => {
          // 得知对象状态是成功的
          // 每个promise对象都成功,就resolve
          count++;
          arr[i] = promises[i];
          if (count === promises.length) {
            resolve(arr);
          }
        },
        (r) => {
          reject(r);
        }
      );
    }
  });
};

手写Promise.race

/**
 * Promise.race的封装
 * @param {Promise []} promises
 */
Promise.race = function (promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(
        (v) => {
          // 谁先运行 谁就决定了结果
          // 修改返回对象的状态为[成功]
          resolve(v);
        },
        (r) => {
          // 修改返回对象的状态为[失败]
          reject(r);
        }
      );
    }
  });
};

async await

async 函数

  1. async函数返回的结果是一个Promise对象(返回状态与then函数类似)
  • 如果返回值是一个非Promise类型的数据,结果就是一个成功的Promise对象,return写什么,成功的结果值就是什么
  • 如果返回值是一个Promise对象,则取决于该Promise对象的状态
  • 抛出异常 就变成rejected
async function test() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, 2000);
    });
}
let res = test();
console.log(res); // fulfilled的Promise

await 表达式

  1. await右侧的表达式一般为promise对象,但也可以是其他的值
  2. 如果表达式是Promise对象,await返回的是Promise成功的值
  3. 如果表达式是其他值,直接将此值作为await的返回值
    本质目的是拿到Promise对象的结果

注意

  1. await必须写在async函数中,但async函数中可以没有await
  2. 如果awaitPromise失败了,则要通过try catch处理
async function test() {
  let p = new Promise((resolve, reject) => {
    // 为成功的情况
    // resolve("OK");
    reject("Error");
  });
  try {
    let res = await p;
  } catch (e) {
    console.log(res);
  }
}

await与async联合使用

用Promise封装一个ajax请求

function sendAjax(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.responseType = "json";
    xhr.open("GET", url);
    xhr.send();
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(xhr.response);
        } else {
          reject(xhr.status);
        }
      }
    };
  });
}
let a = document.getElementById("a");
a.addEventListener("click", async function () { // 如果用await 一定要有async
  let a = await sendAjax("https://api.apiopen.top/api/getImages", {
    type: "animal",
    page: 0,
    size: 10,
  });
  console.log(a);
});
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值