TypeScript - Angular 9 中的 Promise
我正在嘗試在 Angular 中使用 Promise 寫一個同步函數調用,但結果仍然與預期不同。我有兩個使用該服務從 API 下載數據的函數:
getData1(shortcut: string): void {
this.apiServ.getPrice(shortcut).subscribe(
(price: CurrentPrice) => {
this.price = price;
console.log(1);
},
error => this.error = error
);
}
getData2(shortcut: string): void {
this.apiServ.getPrice(shortcut).subscribe(
(price: CurrentPrice) => {
this.price = price;
console.log(2);
},
error => this.error = error
);
}
我正試圖在回應完成後進行下一次函數呼叫。所以:
data(shortcuts) {
this.getData1(shortcuts[0]);
this.getData2(shortcuts[1]);
}
ngOnInit() {
const myPromise = new Promise((resolve) => {
this.data(this.shortcuts);
resolve(3)
});
myPromise.then((value) => {console.log(value)});
}
但是我的瀏覽器列印出這個呼叫順序:
3
1
2
我到底做錯了什麼?
我也嘗試過使用回呼函式,但效果總是一樣。
答案#1
如果你想使用 promises,你可以使用 async/await,但你也可以使用 rxjs 來做到這一點。
可觀察的流
我創建了兩個函數來模擬你的問題,一個叫做 getDataAsObservable,代表你的 getData 方法,另一個叫做 getDataAsPromise,代表你的 promise,然後我使用 concat,它是 rxjs 的一個可觀察對象創建方法,按順序發出給定 Observable 的所有值,然後再移到下一個。
我將第一個、第二個和第三個非同步函數傳給 concat 並訂閱,以便將結果打印出來。
Promise 流程
否則,如果你使用 async/await,你只需要等待回應。
import { Observable, concat } from 'rxjs';
import { delay } from 'rxjs/operators';
async ngOnInit() {
// first execute promise flow and wait for the response
await this.executePromiseFlow();
// after promise flow we can execute observable flow
this.executeObservableFlow();
}
executePromiseFlow = async () => {
// I use toPromise method to convert observable to a promise
const first = await this.getDataAsObservable(1).toPromise();
console.info('[Promise] output', first);
const second = await this.getDataAsObservable(2).toPromise();
console.info('[Promise] output', second);
const third = await this.getDataAsPromise(3);
console.info('[Promise] output', third);
}
executeObservableFlow = () => {
const second$ = this.getDataAsObservable(2);
const first$ = this.getDataAsObservable(1);
const third$ = this.getDataAsPromise(3);
concat(first$, second$, third$)
.subscribe((output) => console.info('[Observable] output', output))
}
getDataAsObservable = (value: number) => {
return new Observable((observer) => {
observer.next(value);
observer.complete();
}).pipe(
delay(value * 2000), // simulate HTTP request time
);
}
getDataAsPromise = (value: number) => {
return Promise.resolve(value);
}
你可以在這裡閱讀更多關於 async/await 的內容,在這裡閱讀更多關於 rxjs 的內容。
你可以在 Stackblitz 這裡查看這個的簡單重現
答案#2
你可以使用 rxjs 的 zip:
import { Observable, zip } from 'rxjs'; import { tap } from 'rxjs/operators';
getData1(shortcut: string): Observable<any> {
return this.apiServ.getPrice(shortcut).pipe(
tap(
(price: CurrentPrice) => {
this.price = price;
console.log(1);
}
)
);
}
getData2(shortcut: string): Observable<any> {
return this.apiServ.getPrice(shortcut).pipe(
tap(
(price: CurrentPrice) => {
this.price = price;
console.log(2);
}
)
);
}
data(shortcuts) : Observable<any> {
const res1 = this.getData1(shortcuts[0]);
const res2 = this.getData2(shortcuts[1]);
return zip(res1, res2);
}
ngOnInit() {
this.data(this.shortcuts).subscribe(() => {
// your code
})
}
