头图

angular 8+中使用observable使用async/await

不废话,直接上结论,jsobservable不能直接使用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)
  }

显而易见,执行结果是
image.png

那么,我想像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)
  }

啊哈,不好,编辑器提示了
image.png

不信邪,运行看看
image.png

正如上面说的,流程控制并没有起作用,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方法才行。
image.png
可以看到,现在程序会等待promise执行完毕以后才会输出2,也就是流程控制生效了。

注意 有些朋友手动写observable的时候,没有在里面写complete,这样执行toPromise的时候,并不会运行then里面代码,因为promise在底层代码完成之前是不会进行解析的,也就是手写observable中一定要记得写complete

当然,转换成promise并不能解决一切问题,比如下面这种情况

当用户点开页面的时候,需要同时发出50个请求,但是用户很可能在所有数据请求结束之前就会跳走,所以很可能20-30个请求都是无效请求,那么,无效请求就需要直接取消掉

我们知道promise是不能够取消已经发出的请求的,你可以通过throw或者reject触发promisecatch操作,但是这只是代表你不再对发出请求的结果关心,请求依然存在,结果依然会返回。
除非用户在所有请求完成之前点击了浏览器的停止加载按钮,
image.png
那请求就会从pending状态变成了cancel
image.png
image.png

或者,使用subscribe,这也是其对比promise的优势之一
取消subscribe请求很简单:
单个请求的情况下

   this.observable.subscribe((res)=>{}).unsubscribe()

直接在后面加上unsubscribe就行,这个请求会变成cancel状态,不会再占用请求资源

那么, 回到上面的问题,简化一下就是,我可不可以,即能取消已经发出的请求,又能控制代码的流程呢?答案是肯定的,只要把promiseobservable一起搭配使用就行
第二种解决办法、 终极版代码如下

  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()
  }

运行结果为
image.png

思路就是通过promise控制代码流程,然后利用对象接收Observable,控制请求的取消与否

这样,即可以按照自己的意愿随时取消已经发出的请求,同时,也能控制代码的流程


跌撞前进的菜鸟
胡乱学习前进中遇到的各种坑与解决办法

现在即是最好。

6 声望
2 粉丝
0 条评论
推荐阅读
猎豹浏览器原生js出现各种各样方法未定义的错误解决办法
想不到2023年了还有人会要求兼容猎豹浏览器。我用原生js写的一个程序,按理来说不应当有兼容性问题,结果页面上报各种方法未定义的错误后面突然想到会不会是因为上一次更新中使用了可选链操作符?.导致的呢把所有...

munergs阅读 179

封面图
正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青56阅读 7.9k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy46阅读 6k评论 12

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.2k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.3k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木44阅读 7.4k评论 6

CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan43阅读 3k评论 14

封面图

现在即是最好。

6 声望
2 粉丝
宣传栏