Skip to content
Spotify - 每月低于 10 元

第12章 异步

setTimeout

  • 设置一个定时器,在定时器到期后执行其中的回调函数
  • setTimeout 只会执行一次

声明定时器

js
// 以下代码输出顺序依次为
// 第一行代码
// 第二行代码
// 1秒后执行
console.log('第一行代码');

let timer = setTimeout(() => {
  console.log('1秒后执行');
}, 1000);

console.log('第二行代码');

清除定时器

  • clearTiemrout() 用于清除 setTimeout
js
// 加上以下代码后,timer 将不会执行
setTimeout(() => {
  clearTimeout(timer);
  console.log('中断timer');
}, 500);

setInterval

  • setInterval 与 setTimeout类似
  • setInterval 每过一段时间就会执行一次
  • clearInterval() 可以用来清除定时器
js
let interval = setInterval(() => {
  let date = new Date();
  console.log(`${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`);
}, 1000);

// 五秒之后取消Interval
setTimeout(() => {
  clearInterval(interval);
}, 5000);

Promise

基本概念

  • Promise 可以创建自定义的异步操作
  • Promise 是一个构造函数

创建 Promise

  • 通过 new 可以创建 Promise 实例对象

  • Promise 在创建后会立即执行(同步)

  • resolve:通过 .then 指定的「成功的回调函数」

  • reject:通过 .then 指定的「失败的回调函数」

js
function odd(number) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (number % 2 !== 0) {
        resolve(`${number}是奇数`);
      } else {
        reject(`${number}不是奇数`);
      }
    }, 500);
  });
}

完成回调

  • Promise可以使用 .then 获取执行结果
  • .then 接受两个参数
    • 第一个为成功的回调函数(必须)
    • 第二个为失败的回调函数(非必须)
js
odd(number).then(
  (res) => {
    console.log('resolve: ' + res);
  },
  (err) => {
    console.log('rejcet: ' + err);
  }
);

异常捕获

  • reject 用于返回异常信息
  • 用 catch 捕获错误信息
  • then 失败回调与 catch 的区别:
    • then 成功回调中抛出的异常,后面的 catch 能捕获到,而 then 的失败回调捕获不到
    • then 的失败回调与 catch 捕获错误信息的时候会采用就近原则
    • 建议总是使用 catch 捕获错误信息,而不使用 then 的第二个参数(失败回调)
js
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('执行失败');
  }, 1000);
});

promise.catch((error) => {
  console.log(error); // 执行失败
});

三种状态

  • pending、resolved、rejected
  • pending 状态,不会触发 then 和 catch
  • resolved 状态,会触发后续的 then 回调
  • rejected 状态,会触发后续的 catch 回调
  • then 正常返回 resolved,里面有报错则返回 rejected
  • catch 正常返回 resolved,里面有报错则返回 rejected

多个 Promise 同时执行

  • Promise.all 可以使多个 Promise 同时执行
    • 所有异步操作全部完成后,会返回一个整体的大 Promise
    • then 之后会返回一个数组,里面为每个 Promise 的返回值
    • 返回值的顺序与传入 Promise 时的顺序相同
  • Promise.race 也可以使多个 Promise 同时执行
    • 第一个 Promise 执行完毕后,返回该 Promise 结果
js
let p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});

let p2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(2);
  }, 2000);
});

let p3 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(3);
  }, 500);
});

Promise.all([p1, p2, p3]).then((values) => {
  console.log(values); // [1, 2, 3]
});

Promise.race([p1, p2, p3]).then((values) => {
  console.log(values); // 3
});

async & await

基本概念

  • async & await用来简化 Promise 异步操作
  • async 创建的函数相当于创建了一个 Promise

使用

  • await 可用于接受另一个 async 函数的结果
  • await 关键字必须在带 async 的函数中调用
  • 出现异常时,可以使用 try...catch 捕获异常
  • 第一个 await 之前的代码会同步执行,之后的会异步执行
js
async function async1() {
  let result2 = await async2();
  let result3 = await async3();
  console.log(result2);
  console.log(result3);
}

async function async2() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(10);
    }, 1000);
  });
}

async function async3() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(5);
    }, 500);
  });
}

async1();

Event Loop

概念

  • JavaScript 是一门单线程执行的编程语言,同一时间只能做一件事
  • 为了防止某个耗时任务导致程序假死,JavaScript 把任务分为同步任务与异步任务

同步任务 & 异步任务

  • 同步任务
    • 主线程上执行
    • 只有前一个任务执行完毕,才能执行后一个任务
  • 异步任务
    • 宿主环境(浏览器、Node)进行执行
    • 当异步任务执行完毕后,会通知主线程执行回调函数
    • 其中异步任务又分为宏任务与微任务

宏任务 & 微任务

  • 宏任务:DOM 渲染后触发
    • 异步 Ajax 请求
    • setTimeout、setInterval
    • 文件操作
  • 微任务:DOM 渲染前触发
    • Promise.then、.catch与.finally
    • process.nextTick

执行顺序

  1. 同步任务由主线程依次执行
  2. 异步任务委托给宿主环境执行
  3. 已完成的异步任务对应的回调函数,会被加入到任务队列中等待执行
  4. 同步任务执行完毕后,查看是否有未执行的微任务,有则执行
  5. 所有微任务执行完毕后,执行下一个宏任务
  6. 每次宏任务执行完毕后,查看是否有未执行的微任务,有则执行
  7. 重复以上步骤
关注微信公众号搬瓦工 - 美国 CN2 优化线路
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0

预览:

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3