遍历方法的Promise对象调用序列(作为返回类型)

时间:2017-10-27 12:22:44

标签: typescript promise

有这种旧的/经典的方法 - 方法返回其他方法调用的结果:

method1(): ObjectX {
   if( condition1 )
      return method2();

   return undefined // or some default value;
}

method2(): ObjectX {
  let res: ObjectX;
  // some IO operations
  return res;
}

现在我想使用Promise<ObjectX>作为method2的返回类型(例如,因为有一些IO操作)。

所以method2变为:

method2() : Promise<ObjectX> {
  return new Promise((resolve)=> {
     let res: ObjectX;
     // some IO operations
     resolve(res);
  })
}

问题在于method1。

为什么IT不能是这样的:

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 - 作为结果类型,我必须大量修改序列中所有方法的代码,而不仅仅是signature和return语句。

还是有其他技术可以达到这个目的吗?

1 个答案:

答案 0 :(得分:1)

你的最终method1过于复杂:

method1() {
   if(condition1) 
      return Promise.resolve(method2());
   return Promise.reject(‘error’); 
}

不需要返回类型:typescript会正确地确定它是Promise<ObjectX>

但即使这样也太复杂了:

async method1() {
   if(condition1) 
      return method2();
   throw 'error';
}

再次method1具有正确的返回类型Promise<ObjectX>

method2()返回ObjectXPromise<ObjectX>时,其中任何一个都是相同的。你永远不需要“解包”一个Promise只是为了返回它的价值,只需将它包含在一个新的承诺中,要么明确表示Promise.resolve(),要么隐含async

这样做的原因以及你的代码不起作用:

return new Promise((reject)=> { reject(‘error’); })

您的新承诺会返回Promise<{}>类型的内容,但返回Promise.reject(something)的类型为Promise<never>

当这些内容与您的Promise<ObjectX>结合使用时,第一个代码会提供无法分配给Promise<ObjectX | {}>的推断返回类型Promise<ObjectX>,但使用Promise.reject()会为您提供Promise<ObjectX | never> 1}}简化为Promise<ObjectX>,因为never类型在组合类型时会消失。

如果您更改的代码非常简单,您可以自己看到这个,因为这个varient会起作用:

return new Promise<never>((reject)=> { reject(‘error’); })