返回

不要再纠结Promise的实现,一文带你快速掌握Promise的精髓

前端

Promise的诞生

在认识Promise之前,有必要知道什么是 回调地狱(Callback Hell)。

无阻塞高并发,是nodeJS的招牌,要达到无阻塞高并发,异步是其基本保障。之前处理异步是通过纯粹的回调函数,例如,使用ajax发起异步请求,然后使用回调函数来处理返回结果。

如果只有一次回调,还好。可一旦回调函数套用几层之后,会发现在处理函数里面一层套着一层,简直就是一场灾难。

这就是回调地狱。

下面我们通过一个小例子来演示下什么是回调地狱。

function getUserInfo(userId, callback) {
  setTimeout(() => {
    callback({
      id: userId,
      name: 'John Doe',
    });
  }, 1000);
}

function getRecentPosts(userId, callback) {
  setTimeout(() => {
    callback([
      {
        id: 1,
        title: 'First Post',
      },
      {
        id: 2,
        title: 'Second Post',
      },
    ]);
  }, 1000);
}

function displayUserInfo(user) {
  console.log(`User ID: ${user.id}`);
  console.log(`User Name: ${user.name}`);
}

function displayRecentPosts(posts) {
  posts.forEach((post) => {
    console.log(`Post ID: ${post.id}`);
    console.log(`Post Title: ${post.title}`);
  });
}

getUserInfo(1, (user) => {
  displayUserInfo(user);
  getRecentPosts(user.id, (posts) => {
    displayRecentPosts(posts);
  });
});

上面的代码中,我们首先定义了两个函数,getUserInfogetRecentPosts,分别用于获取用户信息和获取用户最近的帖子。

然后,我们定义了两个函数,displayUserInfodisplayRecentPosts,分别用于显示用户信息和显示用户最近的帖子。

最后,我们调用 getUserInfo 函数,并传入一个回调函数。在这个回调函数中,我们调用 displayUserInfo 函数来显示用户信息,然后调用 getRecentPosts 函数,并传入一个回调函数。在这个回调函数中,我们调用 displayRecentPosts 函数来显示用户最近的帖子。

这是一个非常简单的例子,但它已经足以说明回调地狱的危害了。想象一下,如果我们的代码中有很多这样的嵌套回调,那将会变得多么难以阅读和维护。

Promise的出现

Promise的出现就是为了解决回调地狱的问题。

Promise是一个表示异步操作的最终完成或失败的承诺。它提供了统一的接口来处理异步操作,使得代码更加清晰易读。

Promise有三个状态:

  • Pending :表示异步操作尚未完成。
  • Fulfilled :表示异步操作已成功完成,并提供了结果。
  • Rejected :表示异步操作已失败,并提供了错误信息。

Promise的使用

使用Promise非常简单,只需要按照以下步骤即可:

  1. 创建一个Promise对象。
  2. 调用Promise对象的then方法来指定异步操作成功完成后的处理函数。
  3. 调用Promise对象的catch方法来指定异步操作失败后的处理函数。

下面我们通过一个例子来说明如何使用Promise。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Hello World!');
  }, 1000);
});

promise.then((result) => {
  console.log(result); // Hello World!
});

上面的代码中,我们首先创建一个Promise对象,并传入一个带有两个参数的函数。

这两个参数分别是resolvereject,它们用于分别表示异步操作成功完成和失败后的处理函数。

然后,我们调用Promise对象的then方法来指定异步操作成功完成后的处理函数。在这个处理函数中,我们使用console.log()函数来输出结果。

最后,我们调用Promise对象的catch方法来指定异步操作失败后的处理函数。在这个处理函数中,我们使用console.log()函数来输出错误信息。

Promise的常见问题

在使用Promise时,经常会遇到一些常见的问题。

1. Promise的链式调用

Promise的链式调用是指连续调用Promise对象的then方法来处理异步操作。

promise
  .then((result) => {
    return result + '!';
  })
  .then((result) => {
    console.log(result); // Hello World!
  });

上面的代码中,我们首先调用Promise对象的then方法来指定异步操作成功完成后的处理函数。

在这个处理函数中,我们使用return语句返回一个新的Promise对象,并将其传入下一个then方法。

然后,我们调用第二个then方法来指定新的Promise对象成功完成后的处理函数。在这个处理函数中,我们使用console.log()函数来输出结果。

2. Promise的异常处理

Promise的异常处理是指在异步操作失败后捕获错误信息。

promise
  .then((result) => {
    throw new Error('Error!');
  })
  .catch((error) => {
    console.log(error.message); // Error!
  });

上面的代码中,我们首先调用Promise对象的then方法来指定异步操作成功完成后的处理函数。

在这个处理函数中,我们使用throw语句抛出一个错误。

然后,我们调用Promise对象的catch方法来指定错误处理函数。在这个错误处理函数中,我们使用console.log()函数来输出错误信息。

3. Promise的并发处理

Promise的并发处理是指同时处理多个异步操作。

const promises = [
  promise1,
  promise2,
  promise3,
];

Promise.all(promises).then((results) => {
  console.log(results); // [result1, result2, result3]
});

上面的代码中,我们首先定义了一个数组promises,其中包含三个Promise对象。

然后,我们调用Promise.all()方法来同时处理这三个Promise对象。

当这三个Promise对象都成功完成时,我们调用then方法来指定处理函数。在这个处理函数中,我们使用console.log()函数来输出结果。

总结

Promise是JavaScript中用于处理异步编程的一大利器,它可以帮助我们避免回调地狱,让代码更加清晰易读。

Promise有三个状态:PendingFulfilledRejected

使用Promise非常简单,只需要按照以下步骤即可:

  1. 创建一个Promise对象。
  2. 调用Promise对象的then方法来指定异步操作成功完成后的处理函数。
  3. 调用Promise对象的catch方法来指定异步操作失败后的处理函数。

在使用Promise时,经常会遇到一些常见的问题,如Promise的链式调用、Promise的异常处理和Promise的并发处理。

掌握了这些知识后,你就可以轻松地使用Promise来处理异步编程了。