异步JavaScript基础笔记

异步JS

浏览器中的Event Loop事件循环

  • JS是单线程的,异步事件依赖于事件循环机制
  • js主线程在执行栈中执行同步任务,如果遇到异步任务,会在幕后线程中执行。
  • 当异步任务执行完成,会将回调函数放到任务队列等待执行
  • 当执行栈中的所有同步任务执行完毕,就会执行任务队列中的任务。
  • 如果当前任务队列为空的话,它就会一直循环等待任务到来,重复获取任务执行任务的过程,这种机制被称为事件循环。
任务队列
  • 宏任务队列:script(整体代码)、setTimeout、setInterval、setImmediate、I/O、UI交互事件、postMessage、MessageChannel;一次事件循环只执行位于宏任务队首的任务,执行完成后立即执行微任务队列中的所有任务(一开始在js主线程中跑的任务就是宏任务,因此执行完主线程的代码后,会从Microtask队列中取任务来执行)
  • 微任务队列:Promise.then、Object.observe、await;宏任务完成后,Event Loop会从微任务队列中取出所有的任务,按照添加的顺序依次执行直到队列为空。
  • 定时器触发器队列:setTimeout和setInterval生成的事件指令的队列。Event Loop在定时器到期后,将处理程序放入适当的宏任务队列中。
  • setTimeout在指定的延迟后执行一次函数,不保证可靠定时,如果主线程忙碌或函数执行时间过长,setTimeout的调用可能会被推迟;而setInterval在指定的间隔后执行函数,无论主线程的忙碌程度如何,如果函数执行时间超过指定间隔,setInterval不会等待上一次调用的完成。
    在定义promise的时候,promise构造部分是同步执行的

Promise

  • 异步函数总是返回一个Promise
  • fetch() API 获取Response对象,返回值赋给Promise对象,操作成功时,Promise 将调用then()方法
  • Promise 链:连续调用异步函数,比如Response对象的json()方法,由于then()方法也会返回promise对象,可以直接在返回值上调用第二个 “then()”
const fetchPromise = fetch(
  "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json",
);

fetchPromise
  .then((response) => {
    return response.json();
  })
  .then((json) => {
    console.log(json[0].name);
  });
  • 错误处理:当异步操作失败时,传递给catch()的处理函数被调用。如果将 catch() 添加到 Promise 链的末尾,它就可以在任何异步函数失败时被调用。
  • fetch() 认为服务器返回一个错误(如404 Not Found)时请求成功,但如果网络错误阻止请求被发送,则认为请求失败。
  • Promise状态:待定(pending)、已兑现(fulfilled)、已拒绝(rejected)
合并Promise:
  • Promise.all()方法接收一个 Promise 数组,并返回一个单一的 Promise。
    当且仅当数组中所有的 Promise 都被兑现时,才会通知 then() 处理函数并提供一个包含所有响应的数组,数组中响应的顺序与被传入 all() 的 Promise 的顺序相同。
    如果数组中有任何一个 Promise 被拒绝。此时,catch() 处理函数被调用,并提供被拒绝的 Promise 所抛出的错误。
Promise.all([fetchPromise1, fetchPromise2, fetchPromise3])
  .then((responses) => {
    for (const response of responses) {
      console.log(`${response.url}${response.status}`);
    }
  })
  .catch((error) => {
    console.error(`获取失败:${error}`);
  });
  • Promise.any()方法当Promise 数组中的任何一个被兑现时,它就会被兑现,只有所有的 Promise 都被拒绝,它才会被拒绝。
async 和 await
  • async:在一个函数的开头添加 async,就可以使其成为一个异步函数。
  • await:异步函数中,在调用一个返回 Promise 的函数之前使用 await 关键字。这使得代码在该点上等待,直到 Promise 被完成,这时 Promise 的响应被当作返回值。
  • await强制异步操作以串联的方式完成,类似Promise链。如果下一个操作的结果取决于上一个操作的结果,这是必要的。
async function fetchProducts() {
  try {
    // 在这一行之后,我们的函数将等待 `fetch()` 调用完成
    // 调用 `fetch()` 将返回一个“响应”或抛出一个错误
    const response = await fetch(
      "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json",
    );
    if (!response.ok) {
      throw new Error(`HTTP 请求错误:${response.status}`);
    }
    // 在这一行之后,我们的函数将等待 `response.json()` 的调用完成
    // `response.json()` 调用将返回 JSON 对象或抛出一个错误
    const json = await response.json();
    console.log(json[0].name);
  } catch (error) {
    console.error(`无法获取产品列表:${error}`);
  }
}
基于 promise 的 alarm API
  • setTimeout(callfunction, ms):启动一个设置为给定延迟的计时器,当时间过期时,它就会调用给定的回调函数。
  • Promise构造函数:Promise() 构造器使用单个函数作为参数,该函数的两个参数分别是resolve和reject;resolve在异步操作成功时调用,reject在异步操作失败时调用。
function alarm(person, delay) {
  return new Promise((resolve, reject) => {
    if (delay < 0) {
      throw new Error("Alarm delay must not be negative");
    }
    window.setTimeout(() => {
      resolve(`Wake up, ${person}!`);
    }, delay);
  });
}

返回的promise中可以调用then()和catch()来设置 promise 兑现和拒绝状态的处理器。

button.addEventListener("click", () => {
  alarm(name.value, delay.value)
    .then((message) => (output.textContent = message))
    .catch((error) => (output.textContent = `Couldn't set alarm: ${error}`));
});
  • 改进:对返回的Promise使用async和await:
button.addEventListener("click", async () => {
  try {
    const message = await alarm(name.value, delay.value);
    output.textContent = message;
  } catch (error) {
    output.textContent = `Couldn't set alarm: ${error}`;
  }
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值