使用Promise.all进行多功能调用

时间:2019-10-28 20:15:47

标签: typescript promise

我具有以下类似的功能

private async p1(): Promise<Result> {
    let p1;
    // Do stuff.

    return p1;
}

private async p5(): Promise<void> {
    // Call some external API.

}

其中有些有return,有些则没有。但是他们所有人都做了非常具体的事情,而且彼此不依赖。

我正在尝试使用Promise.all()异步调用它们,并使它们并行执行(具有快速故障保护功能)。我最多有15个电话,例如以下代码段:

    let [x1, x2, x3] = await Promise.all([
        this.p1,
        this.p2,
        this.p3,
        this.p4,
        this.p5,
        this.p6,
        this.p7,
        this.p8,
        ...
        this.p15
    ]);

但是,我受到了

的欢迎
src/app/view-models/index.ts:69:37 - error TS2345: Argument of type '(Promise<void> | Promise<Result>)[]' is not assignable to parameter of type 'Iterable<void | PromiseLike<void>>'.
  Types of property '[Symbol.iterator]' are incompatible.
    Type '() => IterableIterator<Promise<void> | Promise<Result>>' is not assignable to type '() => Iterator<void | PromiseLike<void>>'.
      Type 'IterableIterator<Promise<void> | Promise<Result>>' is not assignable to type 'Iterator<void | PromiseLike<void>>'.
        Types of property 'next' are incompatible.
          Type '(value?: any) => IteratorResult<Promise<void> | Promise<Result>>' is not assignable to type '(value?: any) => IteratorResult<void | PromiseLike<void>>'.
            Type 'IteratorResult<Promise<void> | Promise<Result>>' is not assignable to type 'IteratorResult<void | PromiseLike<void>>'.
              Type 'Promise<void> | Promise<Result>' is not assignable to type 'void | PromiseLike<void>'.
                Type 'Promise<Result>' is not assignable to type 'void | PromiseLike<void>'.
                  Type 'Promise<Result>' is not assignable to type 'PromiseLike<void>'.
                    Types of property 'then' are incompatible.
                      Type '<TResult1 = Result, TResult2 = never>(onfulfilled?: ((value: Result) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => Promise<...>' is not assignable to type '<TResult1 = void, TResult2 = never>(onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined) => PromiseLike<...>'.
                        Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
                          Types of parameters 'value' and 'value' are incompatible.
                            Type 'Result' is not assignable to type 'void'.

 69         const x = await Promise.all([
                                        ~
 70             this.p1,
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
 81             this.p15
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 82         ]);

如果我尝试仅添加(最多)11个电话,其中任何一个,一切都会按预期进行。添加第12个函数调用后,就会触发上述错误。

有什么我需要的东西或其他解决方法吗?

2 个答案:

答案 0 :(得分:1)

似乎元组类型(异构数组,其中每个元素都有自己的类型)最多仅支持十二个元素。或至少Promise.all的重载声明到此为止,Typescript推断您必须传递一个列表(任意长度,只有一个元素类型)。

一个相当简单的解决方法是嵌套Promise.all结构:

let [x1, x2, x3, _] = await Promise.all([
    this.p1,
    this.p2,
    this.p3,
    Promise.all([
        this.p4,
        this.p5,
        this.p6,
        this.p7,
        this.p8,
        ...
        this.p15
    ]),
]);

答案 1 :(得分:0)

一旦您击中11个元素,我就设法重现了这一点。内置标头lib.es2015.promise.d.ts包含最多10个元素的重载,但是as Bergi mentions,一旦您命中11,就会假定列表项是同质的。

除了嵌套Promise.all外,您还可以使用显式泛型将返回值键入为unknown。这样,您将无法对列表中的元素进行任何有意义的操作,但是除非您打算从列表中拉出无关紧要的特定结果。

// bar is of type Promise<unknown[]>
let bar = Promise.all<unknown>([foo1(), foo2(), foo3(), foo4(), foo5(),
    foo6(), foo7(), foo8(), foo9(), foo10(), foo11(), foo12(), foo13(),
    foo14(), foo15()]);

typescript playground