有一种古老/经典的方法-其他方法调用的方法返回结果:
method1(): ObjectX {
if( condition1 )
return method2();
return undefined // or some default value;
}
method2(): ObjectX {
let res: ObjectX;
// some IO operations
return res;
}
现在我想使用Promise<ObjectX>
作为方法2的返回类型(例如,因为有一些IO操作)。
因此方法2变为:
method2() : Promise<ObjectX> {
return new Promise((resolve)=> {
let res: ObjectX;
// some IO operations
resolve(res);
})
}
问题出在方法1上。
为什么它不能是这样的东西:
method1() : Promise<ObjectX> {
if( condition1)
return this.method2();
return new Promise((reject)=> { reject(‘error’); })
}
为什么一个需要返回promise的方法不能返回另一个方法(类似的promise)的结果?
为什么它必须"打开"收到的承诺,取出结果并用这个结果解决它自己的承诺?
像这样:
method1() : Promise<ObjectX> {
return new Promise((resolve, reject) => {
if( condition1)
method2().then( (r) => resolve(r) ); // take out the result from received promise and resolve my own promise :(
reject(‘error’);
});
}
我的意思是这是有效的,但我想理解为什么以前的方法1不起作用。
更一般地说,假设我有一系列方法,它们相互调用并返回一个对象(返回对象遍历序列)。如果我在最后一个方法中引入Promise作为结果类型,我必须大量修改序列中所有方法的代码,而不仅仅是签名和返回语句。
或者还有其他技术可以做到这一点?
您的最终method1
过于复杂:
method1() {
if(condition1)
return Promise.resolve(method2());
return Promise.reject(‘error’);
}
不需要返回类型:typescript将正确地计算出它是Promise<ObjectX>
。
但即便如此也过于复杂:
async method1() {
if(condition1)
return method2();
throw 'error';
}
并且CCD_ 4再次具有CCD_。
无论method2()
返回ObjectX
还是Promise<ObjectX>
,这两者都是相同的。您永远不应该仅仅为了返回Promise的值而"打开"它,只需要用Promise.resolve()
显式地或用async
隐式地将它包装在一个新的Promise中即可。
这起作用的原因和你的代码没有起作用:
return new Promise((reject)=> { reject(‘error’); })
您的新promise返回的内容类型为Promise<{}>
,但返回的Promise.reject(something)
具有Promise<never>
类型。
当这些与Promise<ObjectX>
组合时,第一个代码会给出一个推断的返回类型Promise<ObjectX | {}>
,它不能分配给Promise<ObjectX>
,但使用Promise.reject()
会得到Promise<ObjectX | never>
,它会简化为Promise<ObjectX>
,因为never
类型在组合这些类型时会消失。
如果你简单地更改了不起作用的代码,你可以自己看到这一点,因为这个变体会起作用:
return new Promise<never>((reject)=> { reject(‘error’); })