跳至主要內容

2721. 并行执行异步函数


2721. 并行执行异步函数open in new window

🟠   🔗 力扣open in new window LeetCodeopen in new window

题目

Given an array of asynchronous functions functions, return a new promise promise. Each function in the array accepts no arguments and returns a promise. All the promises should be executed in parallel.

promise resolves:

  • When all the promises returned from functions were resolved successfully in parallel. The resolved value of promise should be an array of all the resolved values of promises in the same order as they were in the functions. The promise should resolve when all the asynchronous functions in the array have completed execution in parallel.

promise rejects:

  • When any of the promises returned from functions were rejected. promise should also reject with the reason of the first rejection.

Please solve it without using the built-in Promise.all function.

Example 1:

Input: functions = [

() => new Promise(resolve => setTimeout(() => resolve(5), 200))

]

Output:

Explanation:

promiseAll(functions).then(console.log); // [5]

The single function was resolved at 200ms with a value of 5.

Example 2:

Input: functions = [

() => new Promise(resolve => setTimeout(() => resolve(1), 200)),

() => new Promise((resolve, reject) => setTimeout(() => reject("Error"), 100))

]

Output:

Explanation: Since one of the promises rejected, the returned promise also rejected with the same error at the same time.

Example 3:

Input: functions = [

() => new Promise(resolve => setTimeout(() => resolve(4), 50)),

() => new Promise(resolve => setTimeout(() => resolve(10), 150)),

() => new Promise(resolve => setTimeout(() => resolve(16), 100))

]

Output:

Explanation: All the promises resolved with a value. The returned promise resolved when the last promise resolved.

Constraints:

  • functions is an array of functions that returns promises
  • 1 <= functions.length <= 10

题目大意

给定一个异步函数数组 functions,返回一个新的 promise 对象 promise。数组中的每个函数都不接受参数并返回一个 promise。所有的 promise 都应该并行执行。

promise resolve 条件:

  • 当所有从 functions 返回的 promise 都成功的并行解析时。promise 的解析值应该是一个按照它们在 functions 中的顺序排列的 promise 的解析值数组。promise 应该在数组中的所有异步函数并行执行完成时解析。

promise reject 条件:

  • 当任何从 functions 返回的 promise 被拒绝时。promise 也会被拒绝,并返回第一个拒绝的原因。

请在不使用内置的 Promise.all 函数的情况下解决。

提示:

  • 函数 functions 是一个返回 promise 的函数数组
  • 1 <= functions.length <= 10

解题思路

为了并行执行数组中的异步函数并返回一个 Promise,需要手动实现 Promise.all 的功能。Promise.all 的行为是当数组中的所有 Promise 都成功时,返回所有的结果;如果有任何 Promise 失败,则立即拒绝。

  1. 创建一个新的 Promise:该 Promise 将在所有异步函数都成功时解析,或在其中任何一个被拒绝时拒绝。

  2. 创建一个结果数组,用于保存每个函数的结果,以确保最终的结果顺序与输入顺序一致。

  3. 手动维护一个计数器,用于跟踪已完成的 Promise 数量。

  4. 遍历 functions 数组:对于每个函数,手动执行它并对其返回的 Promise 进行处理。

    • 若成功,将函数的成功结果存储在 results 数组中,计数器 count 递增,当所有函数都成功执行时,解析 results 数组。
    • 若任何一个函数返回的 Promise 被拒绝,则立即拒绝整个 Promise,并且抛出第一个错误原因。

复杂度分析

  • 时间复杂度O(n),其中 nfunctions 的数量,需要遍历所有函数并触发它们的执行。
  • 空间复杂度O(n),用于存储函数的结果。

代码

/**
 * @param {Array<Function>} functions
 * @return {Promise<any>}
 */
var promiseAll = function (functions) {
	return new Promise((resolve, reject) => {
		let result = [],
			count = 0;
		functions.map((fn, i) => {
			fn()
				.then((res) => {
					result[i] = res;
					count++;

					// 当所有函数都成功解析时,解析整个结果
					if (count == functions.length) {
						resolve(result);
					}
				})
				.catch((err) => reject(err)); // 一旦有任何函数被拒绝,立即拒绝整个 promise
		});
	});
};

/**
 * const promise = promiseAll([() => new Promise(res => res(42))])
 * promise.then(console.log); // [42]
 */