不废话,直接上结论,js
中observable
不能直接使用async/await
这种流程控制标识,举个例子
observable:Observable<any> = new Observable;
constructor() {
this.observable = Observable.create((item:any)=>{//一秒钟后输出结果
setTimeout(()=>{
item.next('结果');
item.complete();
},1000)
})
}
ngOnInit() {
console.log(1);
let startTime = new Date().getTime()
this.observable.subscribe((res)=>{
let endTime = new Date().getTime()
let result = Math.floor(new Date(endTime-startTime).getTime()/1000);
console.log(res,' 耗时',result,'秒')
})
console.log(2)
}
显而易见,执行结果是
那么,我想像promise
那样使用async/await
是否可以呢?
对ngOnInite()
方法进行稍加改动,加上async/await
async ngOnInit() {
console.log(1);
let startTime = new Date().getTime()
await this.observable.subscribe((res)=>{
let endTime = new Date().getTime()
let result = Math.floor(new Date(endTime-startTime).getTime()/1000);
console.log(res,' 耗时',result,'秒')
})
console.log(2)
}
啊哈,不好,编辑器提示了
不信邪,运行看看
正如上面说的,流程控制并没有起作用,Observable
不支持直接的流程控制。
解决办法有两个,首先说一个简单情况下的解决办法
第一种、转为promise
操作如下
async ngOnInit() {
console.log(1);
let startTime = new Date().getTime()
await this.observable.toPromise().then((res)=>{
let endTime = new Date().getTime()
let result = Math.floor(new Date(endTime-startTime).getTime()/1000);
console.log(res,' 耗时',result,'秒')
})
console.log(2)
}
直接利用.toPromise()
方法将其转为promise
,这样async/await
就起作用了,当然,也要使用promise
中的then
方法才行。
可以看到,现在程序会等待promise
执行完毕以后才会输出2,也就是流程控制生效了。
注意 有些朋友手动写observable
的时候,没有在里面写complete
,这样执行toPromise
的时候,并不会运行then
里面代码,因为promise
在底层代码完成之前是不会进行解析的,也就是手写observable
中一定要记得写complete
当然,转换成promise
并不能解决一切问题,比如下面这种情况
当用户点开页面的时候,需要同时发出50个请求,但是用户很可能在所有数据请求结束之前就会跳走,所以很可能20-30个请求都是无效请求,那么,无效请求就需要直接取消掉
我们知道promise
是不能够取消已经发出的请求的,你可以通过throw
或者reject
触发promise
的catch
操作,但是这只是代表你不再对发出请求的结果关心,请求依然存在,结果依然会返回。
除非用户在所有请求完成之前点击了浏览器的停止加载按钮,
那请求就会从pending
状态变成了cancel
或者,使用subscribe
,这也是其对比promise
的优势之一
取消subscribe
请求很简单:
单个请求的情况下
this.observable.subscribe((res)=>{}).unsubscribe()
直接在后面加上unsubscribe
就行,这个请求会变成cancel
状态,不会再占用请求资源
那么, 回到上面的问题,简化一下就是,我可不可以,即能取消已经发出的请求,又能控制代码的流程呢?答案是肯定的,只要把promise
和observable
一起搭配使用就行
第二种解决办法、 终极版代码如下
observableArray:Subscription=new Subscription;
observable:Observable<any> = new Observable;
constructor() {
this.observable = Observable.create((item:Observer<any>)=>{
setTimeout(()=>{
item.next('完成');
item.complete();
},1000)
})
}
async ngOnInit() {
console.log(1);
let startTime = new Date().getTime()
await new Promise((resolve,reject)=>{
this.observableArray.add(this.observable.subscribe((res)=>{
resolve(true)
let endTime = new Date().getTime()
let result = Math.floor(new Date(endTime-startTime).getTime()/1000);
console.log(res,' 耗时',result,'秒')
}))
})
console.log(2)
}
ngOnDestroy(): void {
this.observableArray.unsubscribe()
}
运行结果为
思路就是通过promise
控制代码流程,然后利用对象接收Observable
,控制请求的取消与否
这样,即可以按照自己的意愿随时取消已经发出的请求,同时,也能控制代码的流程
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。