sai*_*ran 5 javascript async-await es6-promise angular6
我有一个像下面这样的功能
function async populateInventories(custID){
this.inventories = await this.inventoryService.getCustomerInventories(custID)
//do some stuff with Inventories
// another await
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我需要取消一个 Ongoing Await 请求,并像我们使用订阅一样发送一个 Fresh Await 请求。
以前我的功能如下所示,我可以取消以前的订阅:
function async populateInventories(custID){
let invetroySubscription$;
if(invetroySubscription$!==undefined){
invetroySubscription$.unsubscribe();
}
invetroySubscription$=this.inventoryService.getCustomerInventories(custID).subscribe((data:any)=>{
this.inventories = data.response;
//do some stuff with Inventories
// another subscription here -- I was told this way of doing is wrong
})
}
Run Code Online (Sandbox Code Playgroud)
使用 async/await,我能够按顺序处理任何操作,这真的很棒,并且代码非常易读,我无法使用订阅来实现,但是 async/await 有自己的缺点。
我可以一次停止多次调用来填充库存以避免我的问题,但我正在寻找是否可以获得更多解决方案(整洁)来解决我的问题。
PS:我读到在订阅调用或嵌套订阅中调用另一个订阅不是一个好的做法。
处理异步操作的取消取决于我们执行异步操作的类型和方式。
我假设我们的异步操作的类型是 HTTP 请求。因此,我们有多种选择来执行实际的 HTTP 请求:
当使用HttpClient
Angular 本身的服务时,建议将其RxJs
结合使用。因此,对于您的情况,我会切换回您上面描述的 Observable 解决方案。为什么?:
RxJs
并返回 Observables 作为默认值 RxJs
与switchMap操作符结合使用HttpClient
可以“轻松”取消正在进行的请求RxJs
代码并避免多重或嵌套订阅并不那么容易。在你的情况下,我会尝试创建一个(我假设)点击事件流并使用:
this.populateInventoryClicks$
.pipe(
switchMap(() => this.inventoryService.inventoriesRequest()),
concatMap(inventories => this.inventoryService.populateInventoriesRequest(inventories)),
)
.subscribe(response => {
console.log(response);
});
Run Code Online (Sandbox Code Playgroud)
请看一下Stackblitz示例。在开发控制台的网络选项卡中限制速度。在“网络”选项卡中,我们应该看到,在单击多个按钮时,仅完成最后一个请求,并且之前的所有请求都被取消。
在使用axios客户端时,我们可以使用cancel
它为我们提供的方法。如果您对他们的方法感兴趣,请查看他们的文档。请注意,当我们使用 Axios 时, Angular 中的HttpInterceptors不会对这些请求运行。这是我知道没有人将它与 Angular 结合使用的最明显原因。
Fetch API 还为我们提供了中止正在进行的请求的可能性fetch
。我不能推荐这种方法,原因与我不能推荐 Axios 方法的原因相同。但如果你有兴趣的话就看看吧。
小智 0
您可以尝试在 getCustomerInventories 函数内部添加某种回调,以便在您希望取消承诺时解析或拒绝承诺。例如,如果您希望它停止并根据时间发送新的,您可以添加类似的内容
setTimeout(resolve, ms);
Run Code Online (Sandbox Code Playgroud)
到它。
您可以使用Promise.race()来检索原始的等待或超时或其他任何内容。就像是:
//keepGoing and checkGoingFunction could be whatever you need them to be but something that returns a promise that will resolve or reject when you want to "cancel" the await
var keepGoing = true;
var checkGoingFunction = function(){
return new Promise((resolve, reject) => {
while(keepGoing){
//just filling time and keeping a loop, maybe not efficient but working
}
//after it exits (when you change keepGoing to false)
resolve("timedOut");
});
}
function async populateInventories(custID){
//a promise returned by your method
var custInvPromise = this.inventoryService.getCustomerInventories(custID)
var timeoutPromise = checkGoingFunction(); //promise from timeout function
var bigPromise = Promise.race(custInvPromise, timeoutPromise);
//maybe add setTimeout(function(){keepGoing = false}, 5000); if you wanted to timeout after 5 seconds
var result = await bigPromise;
if(result == "timedOut"){
//resend await or whatever you need to do
} else {
this.inventories = result;
//do some stuff with Inventories
}
}
Run Code Online (Sandbox Code Playgroud)