以下是在JS中完美运行的代码:
import Component from '@ember/component';
import {task} from 'ember-concurrency';
class Foo extends Component {
currentRecordId!: string; // passed from template
@task
fetchRecord *(id) {
return yield this.store.findRecord('foo', id);
}
async fetchCurrentRecord() {
return this.fetchRecord.perform(this.currentRecordId);
}
}
Ember并发是Promise的替代方法,它允许取消和管理Promise,类似于RxJS中的Observable。由于JS许诺不允许取消,因此Ember Concurrency使用yield
而不是async
/ await
。
上面使用的task
装饰器将生成器函数转换为具有TaskProperty
方法的.perform()
实例。
请注意,尽管很奇怪,但这种模式已在非类型化JS应用程序中证明了其方便性和可靠性。
但是输入它会带来挑战。
这是
export declare function task<T, A>(generatorFn: () => Iterator<T>): Task<T, () => TaskInstance<T>>;
export declare function task<T, A>(
generatorFn: (a: A) => Iterator<T>
): Task<T, (a: A) => TaskInstance<T>>;
export declare function task<T, A>(
generatorFn: (a: A) => Iterator<PromiseLike<T>>
): Task<T, (a: A) => TaskInstance<T>>;
export declare function task<T, A1, A2>(
generatorFn: (a1: A1, a2: A2) => Iterator<T>
): Task<T, (a1: A1, a2: A2) => TaskInstance<T>>;
// More variants of arguments skipped
export interface TaskInstance<T> extends PromiseLike<T> {
readonly error?: any;
readonly hasStarted: ComputedProperty<boolean>;
readonly isCanceled: ComputedProperty<boolean>;
readonly isDropped: ComputedProperty<boolean>;
readonly isError: boolean;
readonly isFinished: ComputedProperty<boolean>;
readonly isRunning: ComputedProperty<boolean>;
readonly isSuccessful: boolean;
readonly state: ComputedProperty<TaskInstanceState>;
readonly value?: T;
cancel(): void;
catch(): RSVP.Promise<any>;
finally(): RSVP.Promise<any>;
then<TResult1 = T, TResult2 = never>(
onfulfilled?: ((value: T) => TResult1 | RSVP.Promise<TResult1>) | undefined | null,
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null
): RSVP.Promise<TResult1 | TResult2>;
}
interface Task<T> extends TaskProperty<T> {
readonly isIdle: boolean;
readonly isQueued: boolean;
readonly isRunning: boolean;
readonly last?: TaskInstance<T>;
readonly lastCanceled?: TaskInstance<T>;
readonly lastComplete?: TaskInstance<T>;
readonly lastErrored?: TaskInstance<T>;
readonly lastIncomplete?: TaskInstance<T>;
readonly lastPerformed?: TaskInstance<T>;
readonly lastRunning?: TaskInstance<T>;
readonly lastSuccessful?: TaskInstance<T>;
readonly performCount: number;
readonly state: TaskState;
perform(...args: any[]): TaskInstance<T>;
cancelAll(): void;
}
export interface TaskProperty<T> extends ComputedProperty<T> {
cancelOn(eventNames: string[]): this;
debug(): this;
drop(): this;
enqueue(): this;
group(groupPath: string): this;
keepLatest(): this;
maxConcurrency(n: number): this;
on(eventNames: string[]): this;
restartable(): this;
}
这些类型不是官方的,可以自定义。
我很难正确输入最上面的代码示例。
我得到的错误是:
属性
perform
在类型() => IterableIterator<any>
上不存在。
这是可以理解的,因为fetchRecord
被定义为生成器。
此外,TypeScript officially does not support装饰器会更改装饰属性的类型。
所以问题是:如何解决限制并键入这样的修饰符而不返回到@ts-ignore
?
除了键入fetchRecord
属性之外,我还要正确键入传递给this.fetchRecord.perform()
并由生成器接收的参数。
谢谢。 ^ __ ^