angular2 学习笔记 ( Rxjs, Promise, Async/Await 的区别 )

更新 2019-07-17 java

function abc(): Promise<string>{
  return new Promise(resolve => {
     resolve('dada');
     console.log('yeah')
  });
}

resolve 以后你再调用 resolve 外部是不会理会的, 这和 .next 不一样ajax

另外 resolve 也不等于 return;编程

resolve 以后的代码依然会执行.c#

 

 

Promise 是 ES 6promise

Async/Await 是 ES 7异步

Rxjs 是一个 js 库async

在使用 angular 时,你会常常看见这 3 个东西.异步编程

它们都和异步编程有关,有些状况下你会以为用它们其中任何一个效果都同样. 但又以为好像哪里不太对....this

这篇就来讲说,我在开发时的应用方式.url

在 Typescript 尚未支持 Async/Await 的时候, angular 就已经发布了.

那时咱们只想着 Promise vs Rxjs 

这 2 者其实很好选择, 由于 "可读性" 和 "代码量" 是差不错的. 

而 Rxjs 有一些 Promise 没有的特性. 

好比一堆的 operator, 这让咱们很方便的操做 stream, 这是 Promise 没有的. (能够去看看如何用 rxjs 来实现 search text, triple click 等等, 几行代码就能够完成了) 

此外 Rxjs 能够持续的监听和响应, 这点也是 Promise 作不到的. 

因此绝大部分状况下,咱们鼓励开发者使用 Rxjs. 

而在 angular 自带的多种方法中,默认返回的也都是 Rxjs. 

结论是 : 

a.若是要持续监听和响应或则要用 operator 那么必定是选 Rxjs 

b.其它状况就对比 2 者的 "可读性" 和 "代码量" (在没有 Async/Await 的年代, 它们是同样的), 因此仍是选 Rxjs 就对了.

后来, Typescript 支持了 Async/Await

这让状况发生了变化. 

Async/Await 的 "可读性" 是比 Promise 要好的 (代码越复杂,可读性就越好)

因此刚刚的结论 a 依然没有改变

可是结论 b 就有了变数. 

下面咱们来看看对比的代码 

咱们说 Async/Await 可读性高是指 "它的返回方式和咱们写同步代码很类似"

let a = getData(); // 同步代码

let a = await getDataAsync(); // Async/Await 代码 

这是它好读的缘由. 

可是呢.. 当咱们加上错误处理时,它也许就没有那么好了.

async click()
{
    try
    {
        let a = await getDataAsync();
    }
    catch(e)
    {
        // handle error 
    }    
}

Async/Await 是用 catch 来捕获的. 

这和 java, c# 相似, 读起来还算能够, 可是若是你有多个异步代码, 并且要不一样的错误处理呢 ? 

async click()
{
    try
    {
        let a = await this.http.get('urlA');
        let b = await this.http.get('urlB');
        let c = await this.http.get('urlC');
    }
    catch(e)
    {
        // 咱们须要在这里识别出不一样的 error 作不一样的处理 
    }    
}

把成功和失败的逻辑分开, 并不会让代码更好读, 并且还须要写识别错误的逻辑...

因此咱们能够这样写 

async click()
{
    try
    {
        let a = await this.http.get('urlA').catch(e => {
            this.errorMessage = 'A failed';
            throw '';
        });
        let b = await this.http.get('urlB').catch(e => {
            this.errorMessage = 'B failed';
        });
        let c = await this.http.get('urlC');
    }
    catch(e)
    {
        // 什么都不处理 
    }    
}

勉强还行... 可是为何 .catch 里面还须要 throw 呢 ? 为何有一个 "什么都不处理呢" ? 

这是由于 

let a = await this.http.get('urlA').catch(e => {     
    this.errorMessage = 'A failed';    
    // 假设没有 throw, let a 会是 undefined, let b, let c 会继续执行... 
    // 假设 return whatever, let b, let c 也会执行. 
    // 你要中断 let b, let c 只有 2 个方法. 
    // 1. throw '';
    // 2. Promise.reject('');
    // 这是 Async/Await 和 Promise 不一样的地方
});

一旦你 throw 了, 外面就要有人 catch 否则就会 throw 到 angular 的 catch 里头了 (注意个人 click 是 component 的方法).

因此就有了一个 

catch(e)
{
    // 什么都不处理, 实际上是为了防止 throw 到 angular 的 catch 里头 /.\ 
}    

写 Promise 是不须要 try catch 的,由于 Promise 一旦进入 reject 就不可能进入下一个 then 了, 而 Async/Await 须要配搭 try catch throw.

结论 : 

a.若是要持续监听和响应或则要用 operator 那么必定是选 Rxjs

b.其他状况就看我的了

-看惯了 Promise, 又看不惯 try catch 的话建议用 Promise 就行了.

-但若是 2 种方式你都看的习惯, 那么建议写 Async/Await 吧

由于看不惯 Promise 的人, 你写 Promise, 他就死了.

但是看不惯 try catch 的人, 你写 try catch, 他还死不了.

 

另外,

Rxjs 有一个 toPromise 的功能, 这有时候让人很困惑的...

要知道 Rxjs.toPromise() 只有在 rxjs.complete 时才会触发.

也就是说若是一个 rxjs 它须要持续监听, 那么你用 toPromise 就会毁了. 必定要用 subscribe

angular 的 http 发了 ajax 后就会 complete 了, 因此你可使用 toPromise, 可是 ActivatedRoute.paramMap 你 toPromise 就完蛋了, 它不会 complete 因此也就不会触发你的 promise 事件. 

相关文章
相关标签/搜索