在TypeScript中,如何定义返回promise的递归函数

时间:2017-01-24 21:05:03

标签: typescript promise settimeout

我们仍然使用angular 1.5.8并且我尝试编写一个函数来打破部分的长计算。由于承诺可以与返回承诺的函数链接,我想这样写:

<Target Name="BeforePublish">
  <ItemGroup>
    <Content Include="wwwroot\dist\**" />
    <Content Include="wwwroot\lib\**" />
  </ItemGroup>
</Target>

这有效,但TypeScript编译器会抱怨,因为Angular $ timeout服务接受一个返回值的函数,而不是promise:

  

TS2322:输入'IPromise&lt; IPromise&gt;'不能分配给'IPromise'类型。 “IPromise&lt; IResult&gt;”类型中缺少属性“add”。

有没有办法正确定义此函数中的类型?

我可以看到两个选项:

  1. 定义流程以返回interface IResult { add(s: string): void { ... } } function buildResult(): IResult { ... } function handleItem(s: string): string { ... } function doWork(data: string[]): ng.IPromise<IResult> { let i = 0; const result = buildResult(); const process = (): ng.IPromise<IResult> => { for(let start = i; i < start + 100; ++i) { const item = data[i]; if(!item) { return $q.resolve(result); } result.add(handleItem(item)); } return $timeout(process, 20) } return process(); }
  2. 投下退货声明:
  3. any

    有更好的主意吗?

1 个答案:

答案 0 :(得分:0)

$ timeout签名是:

interface ITimeoutService {
    (delay?: number, invokeApply?: boolean): IPromise<void>;
    <T>(fn: (...args: any[]) => T, delay?: number, invokeApply?: boolean, ...args: any[]): IPromise<T>;
    cancel(promise?: IPromise<any>): boolean;
}

(见https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/angular/index.d.ts#L603

因此,$timeout(process, 20)返回IPromise<IPromise<IResult>>,抛出TS2322错误。但是你的代码如何工作?看看$ timeout实现,我们看到了答案:

...
deferred.resolve(fn.apply(null, args));
...

$timeout创建一个新的延迟并将其解析为deferred.resolve(fn.apply(null, args));,当fn返回一个promise时作为一个承诺链。

所以,这里的问题是$ timeout签名! $ timeout签名应该是:

interface ITimeoutService {
    (delay?: number, invokeApply?: boolean): IPromise<void>;
    <T>(fn: (...args: any[]) => T | IPromise<T>, delay?: number, invokeApply?: boolean, ...args: any[]): IPromise<T>;
    cancel(promise?: IPromise<any>): boolean;
}

可以看到一个说明性的测试用例here