返回

Promise.all 实现之我见

前端

前言:JavaScript的异步编程

JavaScript是一种单线程语言,这意味着它一次只能执行一个任务。但是,JavaScript提供了异步编程的机制,允许我们同时执行多个任务。异步编程是通过事件循环实现的,事件循环是一个不断循环的过程,它检查是否有待处理的任务,如果有,就执行它们。

在JavaScript中,有两种常用的异步编程方式:回调函数和Promise对象。回调函数是一种将函数作为参数传递给另一个函数的方式,当另一个函数执行完毕后,它会调用回调函数。Promise对象则是一种表示异步操作的结果的对象,它可以处于三种状态之一:pending(等待)、fulfilled(已完成)和rejected(已拒绝)。

Promise.all:等待所有Promise

Promise.all方法可以等待多个Promise同时完成,并返回一个包含所有Promise结果的新Promise。如果所有Promise都成功完成,新Promise的状态将变为fulfilled,并将所有Promise的结果作为参数传递给它的回调函数。如果任何一个Promise被拒绝,新Promise的状态将变为rejected,并将第一个被拒绝的Promise的错误作为参数传递给它的回调函数。

实现Promise.all

下面我们将一步一步实现Promise.all方法。首先,我们需要创建一个新的Promise实例。

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    // ...
  });
}

接下来,我们需要遍历传入的promises数组,并为每个Promise添加一个监听器。监听器会检查Promise的状态,如果Promise成功完成,则将结果存储到一个数组中,如果Promise被拒绝,则直接调用reject函数,并将错误作为参数传递给它。

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    promises.forEach((promise) => {
      promise.then(
        (result) => {
          results.push(result);
          if (results.length === promises.length) {
            resolve(results);
          }
        },
        (error) => {
          reject(error);
        }
      );
    });
  });
}

最后,我们需要检查promises数组中是否还有未完成的Promise,如果没有,则调用resolve函数,并将results数组作为参数传递给它。

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    promises.forEach((promise) => {
      promise.then(
        (result) => {
          results.push(result);
          if (results.length === promises.length) {
            resolve(results);
          }
        },
        (error) => {
          reject(error);
        }
      );
    });

    // 检查是否还有未完成的Promise
    if (results.length === promises.length) {
      resolve(results);
    }
  });
}

现在,我们已经实现了Promise.all方法。我们可以使用它来等待多个Promise同时完成,并获取所有Promise的结果。

使用Promise.all

我们可以使用Promise.all方法来实现各种各样的异步操作。例如,我们可以使用它来加载多个资源,或者并发执行多个任务。

// 加载多个资源
const images = [
  'image1.jpg',
  'image2.jpg',
  'image3.jpg',
];

Promise.all(images.map((image) => {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      resolve(img);
    };
    img.onerror = () => {
      reject(new Error('Failed to load image'));
    };
    img.src = image;
  });
})).then((images) => {
  // 所有图片已加载完成
  console.log(images);
});

// 并发执行多个任务
const tasks = [
  () => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Task 1 completed');
      }, 1000);
    });
  },
  () => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Task 2 completed');
      }, 2000);
    });
  },
  () => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('Task 3 completed');
      }, 3000);
    });
  },
];

Promise.all(tasks()).then((results) => {
  // 所有任务已完成
  console.log(results);
});

结语

Promise.all方法是JavaScript中一个非常有用的工具,它可以帮助我们等待多个Promise同时完成,并获取所有Promise的结果。我们在本文中实现了Promise.all方法,并探讨了它在实际场景中的应用。希望本文能够帮助你对Promise.all方法有更深入的理解和认识。