如何将Promise.all()与Typescript一起使用

如何将Promise.all()与Typescript一起使用,typescript,Typescript,以下是我想做的: Promise.all([aurelia.start(), entityManagerProvider.initialize()]) .then((results:Array<any>) => { let aurelia: any = results[0]; aurelia.setRoot(); }); Promise.all([aurelia.start(),entityManagerProvider.ini

以下是我想做的:

Promise.all([aurelia.start(), entityManagerProvider.initialize()])
    .then((results:Array<any>) => {
        let aurelia: any = results[0];
        aurelia.setRoot();
    });
Promise.all([aurelia.start(),entityManagerProvider.initialize()]))
.然后((结果:数组)=>{
设aurelia:any=结果[0];
毛状根();
});
aurelia.start()
返回aurelia类型,而
initialize()
返回void

编译器给出一条错误消息,表示无法从用法推断类型


我试图实现的是让它们同时运行,因为它们都是非常长的进程,然后运行
Aurelia.setRoot()

这是TypeScript及其
承诺中的一个弱点。所有签名。通常,最好使用类型一致的数组。您可以手动执行以下操作:

let foo : [Promise<Aurelia>,Promise<void>] = [aurelia.start(), entityManagerProvider.initialize()];
Promise.all(foo).then((results:any[]) => {
    let aurelia: any = results[0];
    aurelia.setRoot();
});
让foo:[Promise,Promise]=[aurelia.start(),entityManagerProvider.initialize()];
Promise.all(foo).then((结果:any[])=>{
设aurelia:any=结果[0];
毛状根();
});

由于
Promise::all
是一个通用函数,因此可以像下面这样声明每个Promise的返回类型:

Promise.all<Aurelia, void>([
  aurelia.start(),
  entityManagerProvider.initialize()
])
.then(([aurelia]) => aurelia.setRoot());
Promise.all([fooPromise, barPromise]).then(([foo, bar]) => {
  // compiler correctly warns if someField not found from foo's type
  console.log(foo.someField);
});
Promise.all([
aurelia.start(),
entityManagerProvider.initialize()
])
.然后(([aurelia])=>aurelia.setRoot());

如果希望保持类型安全,可以扩展
Promise
对象(类型为
PromiseConstructor
)的本机类型定义,并为when
PromiseConstructor
)添加额外的重载签名。调用所有
时,不一定使用可相互分配的有限值:

interface PromiseConstructor
{
    all<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
    all<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
    ...
}

至少从TypeScript
2.7.1
开始,编译器似乎在没有帮助的情况下解析类型,语法如下:

Promise.all<Aurelia, void>([
  aurelia.start(),
  entityManagerProvider.initialize()
])
.then(([aurelia]) => aurelia.setRoot());
Promise.all([fooPromise, barPromise]).then(([foo, bar]) => {
  // compiler correctly warns if someField not found from foo's type
  console.log(foo.someField);
});

帽子提示:@JamieBirch(从评论到@AndrewKirkegaard的回答)

我在寻找
Promise.all()
的返回类型时不知何故来到这里,因为直截了当的
[Promise,Promise]
显然不起作用

最终,事情变得比看上去更简单:

const severalMongoDbOperations: Promise<[DeleteWriteOpResultObject, UpdateWriteOpResult]> =
  () => Promise.all([
    mongo.deleteOne({ ... }),
    mongo.updateOne({ ... })
  ]);

我和你有同样的问题,但是有了这个代码,所有的工作都很完美

type TList = Promise<Aurelia> | Promise<void>;

const foo: TList[] = [aurelia.start(), entityManagerProvider.initialize()];

Promise.all<TList>(foo).then((results) => {
    let aurelia = results[0];
    aurelia.setRoot();
});
type TList=Promise | Promise;
const-foo:TList[]=[aurelia.start(),entityManagerProvider.initialize()];
Promise.all(foo).然后((结果)=>{
设aurelia=results[0];
毛状根();
});

我最喜欢使用的
Promise.all()
当使用promises时,返回值使用数组重组,如下所示。使用
wait
更具可读性,而解构则是填充正确的变量

export interface IDeveVersionHubDataService {
    getBuildFilterDeveVersions(): Promise<IBuildFilterDeveVersionDto[]>;
    getBuildFilterUsers(): Promise<IBuildFilterUserDto[]>;
}
第一部分 有一些函数需要理解A)
承诺。所有
和B)
承诺。然后

A)
Promise.all的类型定义是一个函数:

    all<T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>;
第一部分a
Promise。那么
的类型定义很多,但可以分解为几个小部分:

then
a函数
then
带有两个泛型
TResult1、TResult2
意味着我们以后可以在它们内部设置和使用值-它们被调用

然后
函数本身:
(oncompleted?:…,onrejected?:…):Promise

PromiseLike
是一种助手类型,与
Promise
相同(用于介绍课程)

onfulfilled
onrejected
是以下形式的函数:
(值:T)=>(TResult1或PromiseLike)
未定义
。请注意这里使用的是泛型
T

第二部分- Promise本身有一个通用接口:
接口Promise
是一个/

所以当你打电话的时候

Promise.all<SomeCoolType>([a(), b(), c()]).then( value => doSomething(value) )
Promise.all([a(),b(),c()])。然后(value=>doSomething(value))
您的泛型是
SomeCoolType
,在本例中,某个cool类型是

interface SomeCoolType=[A()=>string,B()=>boolean,C()=>number]

现在请记住,
abc
必须是承诺。这使得它成为
中的
值。然后(value=>…
将进入
SomeCoolType
的结果,我们调用所有这些函数,结果是
[字符串,布尔值,数字]

结论- 具体地说,您传递给您的函数/承诺数组
Promise。所有
都是
中使用的泛型。然后(result=>…)
。这些承诺的返回/解析值将成为
result
的值/类型


示例:
Promise.all]>([returnStringAsync()])。然后(result=>console.log(typeof result==“string”);#=>true

Visual Studio代码批准该语法,但绑定在生成系统中的
tslint
会抱怨:
数组未正确声明,它应该是类型[]或者数组。奇怪的是,搜索该错误消息只会产生0个结果。所以写
让foo:Array=[aurelia.start(),entityManagerProvider.initialize()]
现在看来,这对我来说是纯推理。它返回一种非常有效的承诺类型。我不确定这是由于最近的编译器功能,还是只是ES6承诺的键入现在比以前更好。无论如何,这里的推断令人印象深刻。-1:通过
承诺键入。所有
都比以前更好raightforward比首先声明承诺的类型化数组要好。请看答案:在vscode中,它工作得很好。但是,当我通过tsc编译它时,它会说
错误TS2346:提供的参数与调用目标的任何签名都不匹配。
(tsc-v 2.0.6)。有什么解决方案吗?这会产生“提供的参数与调用目标的任何签名都不匹配。”在2.1.4中也是如此。在Typescript
2.7.2
中,我发现它能够正确推断传递到
then()中的数组中的类型
Promise::all
@JamieBirch谢谢,它似乎也适用于
2.7.1
。我认为这是一个
    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
Promise.all<SomeCoolType>([a(), b(), c()]).then( value => doSomething(value) )