Promise,async,await 知识点

15 篇文章 0 订阅

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,面试题

面试题


以上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,这个问题涉及到JavaScript中的一些异步编程相关的知识点,我会逐一解答。 1. 回调:setTimeout() 回调函数是一种常见的异步编程方式,setTimeout()函数是一个典型的例子。setTimeout()可以在指定的时间之后执行一个回调函数,用法如下: ``` setTimeout(callback, delay); ``` 其中,callback是一个回调函数,delay是一个延迟时间,单位是毫秒。当延迟时间到达时,JavaScript引擎会将回调函数加入到事件队列中,等待执行。 2. promise Promise是一种异步编程的模式,它可以解决回调函数嵌套过多的问题。Promise对象表示一个异步操作的最终完成或失败,并返回一个值。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。当异步操作完成时,Promise会进入fulfilled状态,如果出现错误则会进入rejected状态。可以通过then()方法来注册回调函数,处理Promise对象的状态变化。 3. async/await: async/await是ES7中新增的语法,它使得异步代码的写法更加优雅。async用于声明一个异步函数,await则用于等待一个Promise对象的结果。async函数返回一个Promise对象,可以使用then()方法来注册回调函数。 例如: ``` async function show() { const result = await Promise.resolve("hello"); console.log(result); } show(); ``` 这段代码中,show()函数是一个异步函数,它等待Promise.resolve()返回的结果。当Promise对象的状态变为fulfilled时,show()函数会继续执行,并打印出"hello"。 4. fetch: fetch是一种用于发送HTTP请求的API,它返回一个Promise对象。fetch()函数接受一个URL参数,可以指定请求的地址。fetch()函数返回的Promise对象可以使用then()方法来注册回调函数,处理返回的结果。 例如: ``` fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error)); ``` 这段代码中,fetch()函数发送了一个HTTP请求,请求的地址是https://api.example.com/data。当服务器返回响应时,fetch()函数会返回一个Response对象,我们可以使用response.json()方法将响应体解析为JSON对象。然后我们可以使用then()方法来处理JSON对象。如果发生了错误,我们可以使用catch()方法来捕获异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值