无法使用 Typescript 3.8.3 版本从 NodeJs 12 中的 Promise.allSettled 获取值

Unable to get the value from Promise.allSettled in NodeJs 12 with Typescript 3.8.3 version

我正在学习具有 Promise.allSettled() 功能及其用法的 NodeJs 12。 我写了下面的代码。我能够在控制台中打印状态,但无法打印值,因为它给出了编译问题。

        const p1 = Promise.resolve(50);
        const p2 = new Promise((resolve, reject) =>
            setTimeout(reject, 100, 'geek'));
        const prm = [p1, p2];

        Promise.allSettled(prm).
        then((results) => results.forEach((result) =>
            console.log(result.status,result.value)));

我遇到以下编译问题。

我在下面提供tsconfig.json.

{
  "compilerOptions": {
    "target": "es2017",
    "lib": ["es6","esnext", "dom"],
    "allowJs": true,
    "module": "commonjs",
    "moduleResolution": "node",
    "declaration": true,
    "outDir": "./lib",
    "strict": true,
    "esModuleInterop": true,
    "typeRoots": [ "./types", "./node_modules/@types"]
  },
  "include": ["src"],
  "exclude": ["**/__tests__/*"]
}

如果其中一项承诺被拒绝,您的对象将没有价值。为了警告您这种可能性,TypeScript 使用这种类型:

因此,要从结果中获取价值,您应该使用 guards

const isFilled = <T extends {}>(v: PromiseSettledResult<T>): v is PromiseFulfilledResult<T> => v.status === 'fulfilled';

Promise.allSettled(prm).then((results) => results.forEach((result) =>
    console.log(result.status, isFilled(result) ? result.value : result.status)));

或者自己投

Promise.allSettled(prm).then((results) => results.forEach((result) =>
    console.log(result.status, (result as PromiseFulfilledResult<any>).value)));

您可能想要这样的东西:

  Promise.allSettled(prm).
    then((results) => results.forEach(result => {
       if (result.status === 'fulfilled') {
         console.log(result.status,result.value);
       } else {
         console.log(result.status,result.reason);
       }
    });

value 仅在状态为 fulfilled 时存在,但不包括其中一个 promise 出错的情况。

我看到这里有两个问题。

第一

您创建的第二个承诺是 Promise<unknown> 类型,因为打字稿无法推断其基础类型。

当你创建一个包含两个 promise 的数组时,unknown 会“吞噬”所有内容,你会得到一个 Promise<unknown>[].

类型的数组

如果您这样输入 p2

const p2 = new Promise<number>((resolve, reject) =>
  setTimeout(reject, 100, 'geek'));

你不会有这个问题。

你可能必须为打字稿做这样的事情才能知道承诺是否成功:

Promise.all(prm).then((results) =>
  results.forEach((result) => {
    if (result.status === "fulfilled") {
      console.log("fulfilled", result.value);
    } else {
      console.log("rejected", result.reason);
    }
  })
);

但没有创建特定的 isFullfilled 函数并使用 filter + map

const promises = [
  Promise.reject("Error"),
  Promise.resolve(42),
  Promise.reject("Another error")
]
const results = await Promise.allSettled(promises)
const successes = results
  .filter((x): x is PromiseFulfilledResult<number> => x.status === "fulfilled")
  .map(x => x.value)
const failures: any[] = results
  .filter((x): x is PromiseRejectedResult => x.status === "rejected")
  .map(x => x.reason)

我相信打字系统足够灵活,可以扩展以正确打字

const successes = results
  .filter(x => x.status === "fulfilled")
  .map(x => x.value)
const failures = results
  .filter(x => x.status === "rejected")
  .map(x => x.reason)

但我自己想不出来。