这是我想要做的:
Promise.all([aurelia.start(), entityManagerProvider.initialize()])
.then((results:Array<any>) => {
let aurelia: any = results[0];
aurelia.setRoot();
});
aurelia.start()
返回Aurelia类型,而initialize()
返回void。
编译器会显示一条错误消息,指出无法根据用法推断出该类型。
我想要实现的是让它们同时运行,因为它们都是非常长的进程,然后运行Aurelia.setRoot();
答案 0 :(得分:42)
这是TypeScript及其Promise.all
签名的弱点。通常最好使阵列具有一致的类型。您可以手动执行以下操作:
let foo : [Promise<Aurelia>,Promise<void>] = [aurelia.start(), entityManagerProvider.initialize()];
Promise.all(foo).then((results:any[]) => {
let aurelia: any = results[0];
aurelia.setRoot();
});
答案 1 :(得分:22)
由于Promise::all
是一个泛型函数,你可以像这样声明每个promise的返回类型:
Promise.all<Aurelia, void>([
aurelia.start(),
entityManagerProvider.initialize()
])
.then(([aurelia]) => aurelia.setRoot());
答案 2 :(得分:6)
如果您希望保持类型安全,可以扩展tcp-dump
对象的原生类型定义(类型{{1}带有额外的重载签名,用于在使用有限数量的不一定可分配值调用Promise
时:
PromiseConstructor
根据需要添加尽可能多的重载。此方法为Promise.all
回调的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]>;
...
}
参数中的所有元素提供完全类型安全性:
value
答案 3 :(得分:5)
至少从TypeScript 2.7.1
开始,编译器似乎在没有帮助的情况下解析类型,语法如下:
Promise.all([fooPromise, barPromise]).then(([foo, bar]) => {
// compiler correctly warns if someField not found from foo's type
console.log(foo.someField);
});
帽子小贴士:@JamieBirch(评论@ AndrewKirkegaard的答案)
答案 4 :(得分:3)
您需要了解一些函数 A) Promise.all
和 B) Promise.then
:
A) Promise.all
的类型定义是一个函数:
all<T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>;
B) Promise.then
的类型定义是一个稍微复杂一点的函数:
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.then
的类型定义很多,但可以分解成小部分:
then<TResult1 = T, TResult2 = never>
具有 2 个泛型 then
的函数 TResult1, TResult2
。 < >
表示我们可以稍后在其中设置和使用值 - 它们称为 generics。
then
函数本身:(onfulfilled?: ..., onrejected?: ...): Promise<TResult1 | TResult2>
。
PromiseLike
是辅助类型,与 Promise
相同(用于介绍课程)。
onfulfiled
和 onrejected
是以下形式的函数:(value: T) => (TResult1 OR PromiseLike<TResult1>)
OR undefined
OR null
。请注意此处使用了泛型 T
。
Promise 本身有一个通用接口:interface Promise<T>
。 <T>
是一个/generic。
所以当你打电话
Promise.all<SomeCoolType>([a(), b(), c()]).then( value => doSomething(value) )
你的泛型是 SomeCoolType
,在这个例子中一些很酷的类型是
interface SomeCoolType = [A() => string, B() => boolean, C() => number]
现在记住 A B C
必须是 Promises。这使得 value
中的 .then( value => ...
将转到 SomeCoolType
的结果,对我们来说,它正在调用所有这些函数,结果是 [string, boolean, number]
。
具体而言,您传递给您的函数/承诺数组 Promise.all<T>
是在 .then(result => ...)
中使用的泛型。这些承诺的返回/解析值将成为 result
的值/类型。
示例:Promise.all<[Promise<() => string>]>([returnStringAsync()]).then(result => console.log(typeof result === "string")); # => true
答案 5 :(得分:0)
我在寻找Promise.all()
的返回类型时以某种方式落在这里,因为简单的[Promise<any>, Promise<any>]
显然不起作用。
最终,结果似乎比看起来简单:
const severalMongoDbOperations: Promise<[DeleteWriteOpResultObject, UpdateWriteOpResult]> =
() => Promise.all([
mongo.deleteOne({ ... }),
mongo.updateOne({ ... })
]);
以后可以与.then()
或:
try {
const ops: [DeleteWriteOpResultObject, UpdateWriteOpResult] = await severalMongoDbOperations();
} catch (e) {
// Process rejection
}
答案 6 :(得分:0)
我对您有同样的问题,但是使用此代码,一切都可以正常工作。
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();
});
答案 7 :(得分:0)
在使用返回值的 Promise 时,我最喜欢使用 Promise.all()
使用数组重组,如下所示。使用 await
更具可读性,解构是填充正确的变量。
export interface IDeveVersionHubDataService {
getBuildFilterDeveVersions(): Promise<IBuildFilterDeveVersionDto[]>;
getBuildFilterUsers(): Promise<IBuildFilterUserDto[]>;
}
const loadDeveVersions = deveVersionHubDataService.getBuildFilterDeveVersions();
const loadUsers = deveVersionHubDataService.getBuildFilterUsers();
const [deveVersions, users] = await Promise.all([loadDeveVersions, loadUsers]);