Promise 与 RXJS的区别
回调地狱与 Promise
在使用 Ajax 的过程中,经常会遇到这种情况:我们需要在一个 Ajax 里面嵌套另一个 Ajax 调用,有时候甚至需要嵌套好几层 Ajax 调用,于是就形成了所谓的“回调地狱”:
这种代码最大的问题是可读性非常差,时间长了之后根本无法维护。
Promise 的出现主要就是为了解决这个问题,在 Promise 的场景下,我们可以这样写代码:
new Promise(function(resolve,reject){//异步操作之后用resolve返回data }) .then(function(data){//依赖于Promise的第一个异步操作 }) .then(function(data){//依赖于Promise的第二个异步操作 }) .then(function(data){//依赖于Promise的第三个异步操作 }) .catch(function(reason){//处理异常 });
很明显,这样的代码可读性就强太多了,而且未来维护起来也很方便。
当然,Promise 的作用不止于此,如果你想更细致地研究 Promise,请看 MDN 上的这篇资料。
RxJS 与 Promise 的共同点
RxJS 与 Promise 具有相似的地方,请看以下两个代码片段:
let promise = new Promise(resolve => {setTimeout(() => {resolve('---promise timeout---');}, 2000); }); promise.then(value => console.log(value));
let stream1$ = new Observable(observer => {let timeout = setTimeout(() => {observer.next('observable timeout');}, 2000);return () => {clearTimeout(timeout);} }); let disposable = stream1$.subscribe(value => console.log(value));
可以看到,RxJS 和 Promise 的基本用法非常类似,除了一些关键词不同。Promise 里面用的是 then() 和 resolve(),而 RxJS 里面用的是 next() 和 subscribe()。
RxJS 与 Promise 的3大重要不同点
任何一种技术或者框架,一定要有自己的特色,如果跟别人完全一样,解决的问题也和别人一样,那存在的意义和价值就会遭到质疑。
所以,RxJS 一定有和 Promise 不一样的地方,最重要的不同点有3个,请看下图:
依次给3块代码来示范一下:
let promise = new Promise(resolve => {setTimeout(() => {resolve('---promise timeout---');}, 2000); }); promise.then(value => console.log(value));
let stream1$ = new Observable(observer => {let timeout = setTimeout(() => {observer.next('observable timeout');}, 2000);return () => {clearTimeout(timeout);} }); let disposable = stream1$.subscribe(value => console.log(value)); setTimeout(() => {disposable.unsubscribe(); }, 1000);
从以上代码可以看到,Promise 的创建之后,动作是无法撤回的。Observable 不一样,动作可以通过 unsbscribe() 方法中途撤回,而且 Observable 在内部做了智能的处理,如果某个主题的订阅者为0,RxJS 将不会触发动作。
let stream2$ = new Observable(observer => {let count = 0;let interval = setInterval(() => {observer.next(count++);}, 1000);return () => {clearInterval(interval);} }); stream2$.subscribe(value => console.log("Observable>"+value));
以上代码里面我们用 setInterval 每隔一秒钟触发一个新的值,源源不断,就像流水一样。
这一点 Promise 是做不到的,对于 Promise 来说,最终结果要么 resole(兑现)、要么 reject(拒绝),而且都只能触发一次。如果在同一个 Promise 对象上多次调用 resolve 方法,则会抛异常。而 Observable 不一样,它可以不断地触发下一个值,就像 next() 这个方法的名字所暗示的那样。
let stream2$ = new Observable(observer => {let count = 0;let interval = setInterval(() => {observer.next(count++);}, 1000);return () => {clearInterval(interval);} }); stream2$.filter(val=>val%2==0).subscribe(value => console.log("filter>"+value)); stream2$.map(value => value * value).subscribe(value => console.log("map>"+value));
在上述代码里面,我们用到了两个工具函数:filter 和 map。
- filter 的作用就如它的名字所示,可以对结果进行过滤,在以上代码里面,我们只对偶数值有兴趣,所以给 filter 传递了一个箭头函数,当这个函数的返回值为 true 的时候,结果就会留下来,其它值都会被过滤掉。
- map 的作用是用来对集合进行遍历,比如例子里面的代码,我们把 Observable 返回的每个值都做了一次平方,然后再传递给监听函数。
类似这样的工具方法在 Observable 里面叫做 operator(操作符),所以有人说 Observable 就相当于异步领域的 Underscore 或者 lodash,这样的比喻是非常贴切的。这也是 Observable 比较强的地方,Promise 里面就没有提供这些工具函数。
Observable 里面提供了数百个这样的“操作符”,完整的列表和API文档请参考这里。
我也看到有一些朋友在抱怨,说 RxJS 太过复杂,操作符的数量又特别多,不知道在什么场景下面应该用什么操作符。
实际上这种担心是多余的,因为在 RxJS 里面最常用的操作符不超过10个,不常用的操作符都可以在使用的时候再去查阅文档。
RxJS 和你自己开发的系统一样,常用的功能只有其中的20%,而剩余80%的功能可能永远不会被用到。所以,RxJS 并不像很多人说的那么玄乎,你一定能学会,我相信你。
RxJS 在 Angular 的典型应用场景1:http 服务
this.http .get(url,{search:params}) .map((res:Response) => {let result=res.json();console.log(result);return result; }) .catch((error:any) => Observable.throw(error || 'Server error'));
在新版本的 Angular 里面,http 服务的返回值都是 Observable 类型的对象,所以我们可以 subscribe(订阅)这个对象。当然,Observable 所提供的各种“操作符”都可以用在这个对象上面,比如上面这个例子就用到了 map 操作符。
RxJS 在 Angular 的典型应用场景2:事件处理
this.searchTextStream .debounceTime(500) .distinctUntilChanged() .subscribe(searchText => {console.log(this.searchText);this.loadData(this.searchText) });
这个例子里面最有意思的部分是 debounceTime 方法和 distinctUntilChanged 方法,这是一种“去抖动”效果。“去抖动”这个场景非常能体现 Observable 的优势所在,有一些朋友可能没遇到过这种场景,我来解释一下,以防万一。
在搜索引擎里面,我们经常会看到这样的效果:
这种东西叫做“动态搜索建议”,在用户敲击键盘的过程中,浏览器已经向后台发起了请求,返回了一些结果,目的是给用户提供一些建议。
效果看起来很简单,但是如果没有这个 debounceTime 工具函数,我们自己实现起来是非常麻烦的。这里的难点在于:用户敲击键盘的过程是源源不断的,我们并不知道用户什么时候才算输入完成。所以,如果让你自己来从零开始实现这种效果,你将会不得不使用定时器,不停地注册、取消,自己实现延时,还要对各种按键码做处理。
在 Observable 里面,处理这种情况非常简单,只要一个简单的 debounceTime 加 distinctUntilChanged 调用就可以了。
Promise 与 RXJS的区别相关推荐
- angular2 学习笔记 ( Rxjs, Promise, Async/Await 的区别 )
Promise 是 ES 6 Async/Await 是 ES 7 Rxjs 是一个 js 库 在使用 angular 时,你会经常看见这 3 个东西. 它们都和异步编程有关,有些情况下你会觉得用它们 ...
- promise 和 async await区别
什么是Async/Await? async/await是写异步代码的新方式,以前的方法有回调函数和Promise. async/await是基于Promise实现的,它不能用于普通的回调函数. as ...
- Promise.all()、Promise.allSettled()、Promise.any()、Promise.race()用法与区别
概述 Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值 一个 Promise 必然处于以下几种状态之一: 待定(pending): 初始状态,既没有被兑现,也没有被拒绝. 已兑 ...
- promise 和 Observable 的区别
StackOverflow 上的讨论:What is the difference between Promises and Observables? 得赞最高的一个回答:1777 赞 当异步操作完成 ...
- 2019年12月前端面经及总结(西安,杭州)
2019年12月前端面经及总结(西安,杭州) 我的github主页:https://github.com/dashnowords 我的新书上架啦,3天即登京东计算机编程语言类排行榜Top1!!!精选3 ...
- C++ 中 async、packaged_task、promise 区别及使用
Introduction 编程难,多线程编程更难 – 鲁迅 多线程编程,如此令人着迷.令人痛恨的字眼.人类为了追求更好的效率.更快的速度,非常残忍的发明了多线程编程,这不仅让写代码的难度陡增,同时也加 ...
- 浅谈Generator和Promise原理及实现
Generator 熟悉ES6语法的同学们肯定对Generator(生成器)函数不陌生,这是一个化异步为同步的利器. 栗子: function* abc() {let count = 0;while( ...
- promise用法_图解 Promise 实现原理(四):Promise 静态方法实现
作者:Morrain 转发链接:https://mp.weixin.qq.com/s/Lp_5BXdpm7G29Z7zT_S-bQ 前言 Promise 是异步编程的一种解决方案,它由社区最早提出和实 ...
- promise链式调用_这一次,彻底弄懂 Promise
Promise 必须为以下三种状态之一:等待态(Pending).执行态(Fulfilled)和拒绝态(Rejected).一旦Promise 被 resolve 或 reject,不能再迁移至其他任 ...
最新文章
- 病毒周报(091102至091108)
- ICML 2020论文贡献榜排名出炉:Google单挑斯坦福、MIT、伯克利;清华进TOP 20
- Android Jetpack组件之Navigation使用-源码
- 利用开源中国提供的代码仓库提高github下载速度
- 使用 Spring Cloud 实现微服务系统
- HTML 事件响应函数,HTML5: 事件处理函数的this指向问题
- 你知道url中的特殊符号含义么
- 汉字的Unicode表位置
- Cadence Allegro剪断走线图文教程及视频演示
- 什么是函数指针 ? 什么是指针函数? int (*P)( ) 和int *p()有什么区别
- 彻底理解样本方差为何除以n-1
- Ubuntu版本及对应的代号(4.10-22.04) 共18年整理
- 数据文化 | Uber的数据治理
- MYSQL基本操作(增删改查)
- 统一自定义idea和eclipse代码格式化和注释格式化总结
- 2021csp-j2 题解
- 穷人python入门教程视频_穷的解释|穷的意思|汉典“穷”字的基本解释
- 中 华 百 家 姓 一 览
- icinga用NSCA监控远程Linux服务器
- python中math的ln_Python math库 ln(x)运算的实现及原理