返回

JavaScript 异步编程史:从回调到 Promise 再到 async/await

前端

JavaScript 异步编程史

早期的 Web 应用中,与后台进行交互时,需要进行 form 表单的提交,然后在页面刷新后给用户反馈结果。在页面刷新过程中,后台会重新返回一段 HTML 代码,这段 HTML 中的大部分内容与之前页面相同,只有少部分内容发生变化,比如某个字段的值发生了变化。这种方式虽然简单,但效率低下,而且用户体验也很差。

随着 AJAX 技术的出现,Web 开发人员可以向服务器发送异步请求,而无需刷新整个页面。这极大地提高了 Web 应用的性能和用户体验。

回调

回调函数是一种在异步操作完成后执行的函数。在 JavaScript 中,回调函数通常作为参数传递给异步函数。例如,以下代码使用回调函数来处理服务器返回的数据:

function getData(callback) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'data.json');
  xhr.onload = function() {
    if (xhr.status === 200) {
      callback(JSON.parse(xhr.responseText));
    }
  };
  xhr.send();
}

getData(function(data) {
  console.log(data);
});

回调函数的使用使得 JavaScript 异步编程成为可能,但它也存在一些缺点:

  • 可读性差。 回调函数通常嵌套在其他函数中,这使得代码很难阅读和理解。
  • 难以调试。 回调函数通常是匿名的,这使得它们很难在调试器中进行调试。
  • 难以维护。 回调函数通常与特定的异步操作相关,这使得它们很难重用。

Promise

Promise 对象表示异步操作的最终完成或失败。它可以被用来替代回调函数,使代码更加清晰和易于维护。

以下代码使用 Promise 对象来处理服务器返回的数据:

function getData() {
  return new Promise(function(resolve, reject) {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'data.json');
    xhr.onload = function() {
      if (xhr.status === 200) {
        resolve(JSON.parse(xhr.responseText));
      } else {
        reject(new Error('Error getting data'));
      }
    };
    xhr.send();
  });
}

getData()
  .then(function(data) {
    console.log(data);
  })
  .catch(function(error) {
    console.error(error);
  });

Promise 对象的使用使得 JavaScript 异步编程更加清晰和易于维护,但它也存在一些缺点:

  • 不兼容旧浏览器。 Promise 对象不兼容 IE11 及更早的浏览器。
  • 难以处理多个异步操作。 Promise 对象只能处理单个异步操作。如果要处理多个异步操作,需要使用更高级的技术,如 async/await。

async/await

async/await 语法是 JavaScript 中处理异步操作的最新方式。它允许您使用同步的方式编写异步代码,从而使代码更加清晰和易于理解。

以下代码使用 async/await 语法来处理服务器返回的数据:

async function getData() {
  const response = await fetch('data.json');
  const data = await response.json();
  console.log(data);
}

getData();

async/await 语法是处理异步操作的最佳方式,但它也存在一些缺点:

  • 不兼容旧浏览器。 async/await 语法不兼容 IE11 及更早的浏览器。
  • 需要使用 Babel 或 TypeScript。 为了在旧浏览器中运行 async/await 代码,需要使用 Babel 或 TypeScript 来将代码转换为旧浏览器可以理解的代码。

最佳实践

在编写异步代码时,应遵循以下最佳实践:

  • 使用 async/await 语法。 async/await 语法是处理异步操作的最佳方式,它使代码更加清晰和易于理解。
  • 使用 Promise 对象。 如果不能使用 async/await 语法,则可以使用 Promise 对象来处理异步操作。Promise 对象使代码更加清晰和易于维护。
  • 避免使用回调函数。 回调函数通常嵌套在其他函数中,这使得代码很难阅读和理解。
  • 妥善处理错误。 在编写异步代码时,应始终妥善处理错误。可以使用 Promise 对象的 catch() 方法来处理错误。
  • 使用库或框架。 有许多库或框架可以帮助您编写更有效、更易于维护的异步代码。一些流行的库或框架包括 jQuery、Axios 和 Redux。