JavaScript异步编程

106 阅读4分钟

一、JavaScript异步编程方式

JavaScript异步编程方式有回调函数、promise、Generator、async。

(一)回调函数

当使用回调函数进行异步编程时,可能会出现代码嵌套过深的情况,导致代码变得难以理解和维护。同时,由于多个回调函数的嵌套,使得代码的耦合度过高,不利于代码的模块化和复用。

function asyncFunc1(callback) {
  setTimeout(() => {
    console.log("异步操作1完成");
    callback();
  }, 1000);
}

function asyncFunc2() {
  console.log("异步操作2开始");
  asyncFunc1(() => {
    console.log("回调函数嵌套");
  });
  console.log("异步操作2结束");
}

asyncFunc2();

(二)Promise

Promise 提供了一种链式调用的方式来解决回调函数地狱的问题,但在多个 Promise 串联的情况下,可能会导致代码的语义不够清晰。

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log("Promise异步操作完成");
    resolve();
  }, 1000);
});

promise
  .then(() => {
    console.log("Promise then 调用");
  })
  .catch((err) => {
    console.log("Promise catch 调用");
  });

(三)Generator

Generator 允许在函数的执行过程中暂时将执行权转移给其他函数或异步操作,然后在执行完成后自动恢复执行。这种机制可以让我们以同步的方式编写异步逻辑,但需要解决何时恢复执行权的问题,通常需要借助自动执行 Generator 的机制来实现。

function* generatorFunc() {
  yield new Promise((resolve) => {
    setTimeout(() => {
      console.log("Generator异步操作完成");
      resolve();
    }, 1000);
  });
}

let generator = generatorFunc();
let res = generator.next(); // 开始执行生成器函数,遇到yield语句,暂停执行,返回一个对象{value: ..., done: ...}
while (!res.done) {
  // 如果done属性为false,继续执行生成器函数,直到遇到下一个yield语句,然后暂停,返回一个对象{value: ..., done: ...}。如果done属性为true,说明生成器函数已经执行完毕。
  res = generator.next();
}

(四)Async

Async 函数是一种更简洁、自动执行的语法糖,它基于 Promise 实现,通过 await 关键字等待异步操作的完成。Async 函数允许我们将异步逻辑转化为同步的顺序,并提供自动执行的能力,简化了异步编程的流程。

async function asyncFunc() {
  console.log("Async 函数开始");
  await new Promise((resolve, reject) => {
    // 遇到await语句,暂停执行,返回一个Promise对象。当Promise对象的状态变为resolve后,继续执行async函数。如果Promise对象的状态变为reject,抛出异常。
    setTimeout(() => {
      console.log("Async 异步操作完成");
      resolve();
    }, 1000);
  });
  console.log("Async 函数结束"); // 在这里,由于前面有await语句,所以这个语句会在异步操作完成后执行。
}
asyncFunc(); // 自动执行async函数。如果async函数内部有await语句,那么这个函数会等待所有的await语句都执行完成后,再继续执行。

二、JavaScript异步编程的优劣

(一)优势

  1. 提高性能:异步编程可以避免线程阻塞,提高程序的执行效率。在处理大量计算或IO操作时,不会消耗过多的系统资源,从而提高程序的性能。
  2. 更好的用户体验:异步编程可以减少用户界面的延迟,提高应用程序的响应速度。当程序需要执行一些耗时的任务时,不会阻止用户界面的响应用户的操作,从而提供更好的用户体验。
  3. 更好的服务器端应用:异步编程可以更好地处理高并发请求,提高服务器的处理能力。由于异步请求不会阻塞服务器,因此可以同时处理更多的请求,适用于大规模的服务器端应用。

(二)劣势

  1. 代码复杂度增加:异步编程需要使用回调函数、Promise等异步编程模式,使得代码变得更加复杂,可读性和可维护性降低。
  2. 错误处理难度增加:异步编程中,错误可能发生在不同的时间点,需要使用特定的方式来捕获和处理错误,增加了错误处理的难度。
  3. 资源占用较多:由于异步编程需要创建多个线程或进程来同时执行任务,因此需要更多的系统资源,如内存、CPU等。在资源有限的情况下,可能会影响程序的性能。