The goal I want to achieve is to have a pipe that would handle the following signature :
any | (() => any | Promise<any>)
So I wrote the following pipe.
public transform(varOrFunc: any | (() => any | Promise<any>)): any {
if (typeof varOrFunc === 'function') {
const result = varOrFunc();
if (result.then) {
return this.asyncPipe.transform(result);
} else {
return result;
}
} else {
return varOrFunc;
}
}
--
<my-cmp [isDisabled]="myVarOrFunc | varOrFunc></my-cmp>
Unfortunately this doesn't work as expected.
But
public transform(varOrFunc: any | (() => any | Promise<any>)): any {
if (typeof varOrFunc === 'function') {
const result = varOrFunc();
if (result.then) {
return result;
} else {
return Promise.resolve(result);
}
} else {
return Promise.resolve(varOrFunc);
}
}
--
<my-cmp [isDisabled]="myVarOrFunc | varOrFunc | async ></my-cmp>
Does work perfectely fine.
Do you have any idea why ?
Here is a working demo of the problem
You can't use the AsyncPipe to synchronously transform an asynchronous result. The way the async pipe works is by storing the promise and triggering a change detection when it's resolved, and caching the result. So the transform method of the async pipe will always return null the first time it's called.
I think that the best way to achieve what your trying to do is by reimplementing some of the async pipe logic in your pipe :
for exemple :
@Pipe({ name: "varOrFuncAsync", pure: false })
export class VarOrFuncAsyncPipe implements PipeTransform {
private lastResult: any = null;
private lastParam: any | (() => any | Promise<any>) = null;
constructor(private _ref: ChangeDetectorRef) {}
public transform(varOrFunc: any | (() => any | Promise<any>)): any {
if (this.lastParam === varOrFunc) {
return this.lastResult;
}
this.lastParam = varOrFunc;
if (typeof varOrFunc === "function") {
const result = varOrFunc();
if (result.then) {
this.lastResult = null;
result.then(r => this.updateResult(r));
return null;
} else {
this.lastResult = result;
return result;
}
} else {
this.lastResult = varOrFunc;
return varOrFunc;
}
}
updateResult(result: any) {
this.lastResult = result;
this._ref.detectChanges();
}
}