手写 Promise.allSettled:如何确保无论成功失败都能返回所有结果的状态?

技术讲座:深入理解并实现 Promise.allSettled

引言

在 JavaScript 的异步编程中,Promise 对象是处理异步操作的关键。Promise.all 是一个非常有用的方法,它允许你同时处理多个异步操作,并返回一个单一的 Promise,该 Promise 在所有给定的 Promise 都已解决或拒绝时解决。然而,Promise.all 只在所有输入的 Promise 都成功解决时才会成功,如果有任何一个 Promise 拒绝,则整个 Promise.all 会立即拒绝。为了解决这个问题,Promise.allSettled 被引入了。本文将深入探讨 Promise.allSettled 的概念,并提供一个完整的实现。

一、Promise.allSettled 简介

Promise.allSettled 方法接受一个 Promise 数组作为参数,并返回一个新的 Promise。这个新的 Promise 会在所有输入的 Promise 都被解决或拒绝时解决,并且会返回一个对象数组,每个对象表示一个原始 Promise 的状态。

Promise.allSettled 返回值结构

{
  status: 'fulfilled' | 'rejected',
  value?: any,
  reason?: any
}
  • status: Promise 的状态,可以是 'fulfilled''rejected'
  • value: 如果 Promise 解决,则包含 Promise 的值。
  • reason: 如果 Promise 拒绝,则包含拒绝的原因。

二、Promise.allSettled 工作原理

Promise.allSettled 使用 Promise.finally 方法确保无论 Promise 成功还是失败,都会执行一个回调函数。这个回调函数负责处理所有的结果,并将它们打包成一个数组。

三、实现 Promise.allSettled

下面是一个使用 JavaScript 实现的 Promise.allSettled 方法:

function allSettled(promises) {
  return Promise.all(
    promises.map(p => p.then(
      value => ({ status: 'fulfilled', value }),
      reason => ({ status: 'rejected', reason })
    ))
  );
}

示例

allSettled([Promise.resolve(1), Promise.reject('error'), Promise.resolve(3)])
  .then(results => {
    console.log(results);
    // [
    //   { status: 'fulfilled', value: 1 },
    //   { status: 'rejected', reason: 'error' },
    //   { status: 'fulfilled', value: 3 }
    // ]
  });

四、跨语言实现

PHP

function allSettled($promises) {
    $results = [];
    foreach ($promises as $promise) {
        $results[] = $promise->then(
            function ($value) {
                return ['status' => 'fulfilled', 'value' => $value];
            },
            function ($reason) {
                return ['status' => 'rejected', 'reason' => $reason];
            }
        );
    }
    return Promise::all($results);
}

Python

def all_settled(promises):
    return [promise.result() for promise in promises]

Shell

#!/bin/bash
set -e

promises=("$@")
results=()

for promise in "${promises[@]}"; do
    if $promise; then
        results+=("fulfilled")
    else
        results+=("rejected")
    fi
done

echo "Results: ${results[*]}"

SQL

CREATE TABLE promises (
    id INT PRIMARY KEY,
    status VARCHAR(10),
    value INT,
    reason VARCHAR(255)
);

INSERT INTO promises (id, status, value, reason) VALUES (1, 'fulfilled', 1, NULL);
INSERT INTO promises (id, status, value, reason) VALUES (2, 'rejected', NULL, 'error');
INSERT INTO promises (id, status, value, reason) VALUES (3, 'fulfilled', 3, NULL);

SELECT * FROM promises;

五、总结

Promise.allSettled 是一个非常有用的工具,它允许开发者以非侵入的方式处理异步操作的结果。通过本文,我们深入了解了 Promise.allSettled 的概念和实现方法,并提供了不同语言的实现示例。希望本文能帮助你更好地理解和应用 Promise.allSettled

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注