📜  做出承诺 - Javascript (1)

📅  最后修改于: 2023-12-03 15:22:30.551000             🧑  作者: Mango

做出承诺 - JavaScript

在软件开发中,承诺是一种非常重要的行为。它意味着你向其他开发人员、项目经理、以及最终客户保证,在一定时间内完成一定的工作。

在 JavaScript 中,我们可以使用 Promise 对象来管理异步代码块的执行。Promise 对象代表了一个异步操作的状态,可以是未完成、已完成或者执行失败等状态。

为什么需要 Promise

在 JavaScript 中,我们经常需要处理异步操作,例如从服务器获取数据、读取文件等等。这些操作通常需要花费一定的时间,我们不能一直等待它们完成,然后再继续执行。

在过去,我们通常会使用回调函数来处理异步代码块的执行。但是,这种方式存在一些问题:

  • 回调函数嵌套过深,导致代码难以阅读和维护。
  • 回调函数无法正常处理错误,错误一旦发生,就会导致整个应用崩溃。
  • 回调函数无法处理多个异步操作的执行顺序和结果。

为了解决这些问题,Promise 对象应运而生。

Promise 的基本用法

Promise 对象有三种状态:未完成、已完成、执行失败。它们分别对应着三个函数:

  • new Promise(executor):创建一个新的 Promise 对象,接受一个 executor 函数作为参数。executor 函数会接受两个函数作为参数,分别是 resolvereject,用于设置 Promise 的状态为已完成或执行失败。
  • then(onFulfilled[, onRejected]):为 Promise 添加完成和执行失败的回调函数,返回一个新的 Promise 对象。
  • catch(onRejected):为 Promise 添加执行失败的回调函数,返回一个新的 Promise 对象。

下面是一个简单的例子,使用 Promise 对象异步加载图片:

function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    var img = new Image();

    img.onload = function() {
      resolve(img);
    };

    img.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    img.src = url;
  });
}

这个函数返回一个 Promise 对象,我们可以使用 thencatch 方法来处理 Promise 对象的状态:

loadImageAsync('https://www.example.com/image.jpg')
  .then(function(img) {
    console.log('Image loaded: ' + img.src);
  })
  .catch(function(error) {
    console.error(error);
  });
Promise 的高级用法

Promise 对象的高级用法主要包括以下几个方面:

  • Promise.all()
  • Promise.race()
  • Promise.resolve()
  • Promise.reject()
  • async/await
Promise.all()

Promise.all(iterable) 方法用于将多个 Promise 对象封装成一个新的 Promise 对象,这个新的 Promise 对象在所有的 Promise 对象都执行成功时才成功,其中任何一个 Promise 对象执行失败都会导致新的 Promise 对象执行失败。

例如下面的代码,将同时发起多个请求,只有所有请求返回结果之后才会执行 then 回调函数:

Promise.all([
  fetch('/api/user/1'),
  fetch('/api/user/2'),
  fetch('/api/user/3')
])
  .then(function(responses) {
    // 处理所有请求的结果
  })
  .catch(function(error) {
    // 处理任何一个请求执行失败的情况
  });
Promise.race()

Promise.race(iterable) 方法用于将多个 Promise 对象封装成一个新的 Promise 对象,这个新的 Promise 对象在任何一个 Promise 对象执行成功或执行失败时都会执行回调函数,只要有一个 Promise 对象执行成功或执行失败就会结束这个新的 Promise 对象的执行。

例如下面的代码,将同时发起多个请求,只要有任何一个请求返回结果就会执行 then 回调函数:

Promise.race([
  fetch('/api/user/1?timeout=1000'),
  new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject(new Error('Timeout'));
    }, 2000);
  })
])
  .then(function(response) {
    // 处理第一个请求返回的结果
  })
  .catch(function(error) {
    // 处理超时错误
  });
Promise.resolve()

Promise.resolve(value) 方法创建一个已完成的 Promise 对象,返回的 Promise 对象的结果为 value。

例如下面的代码,创建一个已完成的 Promise 对象,返回的 Promise 对象的结果为字符串 'Hello World!'。

Promise.resolve('Hello World!')
  .then(function(value) {
    console.log(value);
  });
Promise.reject()

Promise.reject(reason) 方法创建一个执行失败的 Promise 对象,返回的 Promise 对象的执行失败的原因为 reason。

例如下面的代码,创建一个执行失败的 Promise 对象,返回的 Promise 对象的执行失败的原因为一个 Error 对象。

Promise.reject(new Error('Something went wrong...'))
  .catch(function(error) {
    console.error(error);
  });
async/await

asyncawait 是 ES2017 中引入的新特性,用于简化异步代码的编写。

async 关键字用于将函数声明为异步函数,异步函数会返回一个 Promise 对象。

例如下面的代码,使用 async 声明了一个异步函数 loadUsers(),这个函数返回一个 Promise 对象。

async function loadUsers() {
  var response = await fetch('/api/users');

  return await response.json();
}

await 关键字用于等待一个 Promise 对象执行完成,并返回执行完成的结果。如果 Promise 对象执行失败,则会抛出一个错误,并阻塞代码的执行。

例如下面的代码,使用 await 等待一个 Promise 对象 loadUsers(),代码会一直阻塞直到 Promise 对象执行完成,并返回执行完成的结果。

async function getUsers() {
  var users = await loadUsers();

  console.log(users);
}
结论

Promise 对象是 JavaScript 中处理异步操作的一种非常重要的方式。使用 Promise 对象能够优雅地处理异步操作的执行顺序和结果,使得代码更加简洁、易于维护和阅读。同时,Promise 对象的高级用法也能够更好地解决各种异步操作的复杂问题,值得开发人员深入理解和掌握。