在现代的前端开发中,异步编程是一种非常常见的需求。ES6 中引入的 Promise 已经在大多数场景中代替了传统的回调函数,但是在某些异步场景下,它仍然存在一些缺点和限制。ES7 中,Observable 被引入成为一种新的异步解决方案,它的强大和灵活性使其在某些场景下,比 Promise 更加适用。
Promise 的特点和限制
Promise 是由 ECMAScript 6 引入的一种新的异步编程方式。它的主要特点是:
- 通过 then() 方法实现链式调用;
- 不需要额外的参数来传递成功或失败的数据,而是通过 resolve() 和 reject() 方法传递;
- 可以通过 catch() 方法捕捉异常;
- 只能返回单个值或者错误。
Promise 的优点是它比传统的回调函数更加清晰和简洁,能够清晰地表达异步操作成功或失败的状态,并能够简单地处理异常。但是,Promise 还存在一些限制:
- Promise 只能携带一次结果,无法处理多次返回结果的情况;
- Promise 无法表示中间结果,因此无法开始、停止和暂停;
- Promise 无法改变已经发出的操作。
以上限制使得 Promise 在某些异步场景下变得不够灵活和有效,因此 Observable 被引入作为一种新的解决方案。
Observable 的特点和优势
Observable 是一个非常强大且灵活的异步解决方案。它的主要特点是:
- 支持多次返回结果,具有异步集合的能力;
- 可观察对象能够表示中间结果,并且可以开始、停止和暂停;
- 可观察对象提供了一套强大的操作符用于转换流。
Observable 的灵活性使得它在一些较为复杂的异步场景下表现出更强的优势。例如,由于 Observable 支持暂停和继续,因此在处理用户输入之类的场景下,Observable 能够更好地掌握流的控制,不必依赖于网络请求的响应速度。同时,由于它具有多次返回结果的能力,Observable 更适合用于流媒体和游戏开发等领域,而不仅仅局限于单次请求/响应的场景。
Promise 和 Observable 的转换
在实践中,我们时常需要将 Promise 转换为 Observable 或是反过来,以适应不同的异步场景。
有时候我们需要将一个 Promise 转换成 Observable,例如在 Vue.js 中使用 axios 发送请求:
import { from } from 'rxjs'; import axios from 'axios'; const promise = axios.get('/api'); const observable = from(promise);
这里使用了 RxJs 中的 from 操作符,将 axios 的返回值 promise 转换成了一个可观察对象。
另外,我们也可以将 Observable 转换成 Promise:
import { of } from 'rxjs'; import { map } from 'rxjs/operators'; const observable = of('hello', 'world'); const promise = observable .pipe(map(val => val.toUpperCase())) .toPromise();
在上述代码中,我们使用了 RxJs 中的 pipe 和 toPromise 方法将 Observable 转换成了 Promise。
Observable 的异步流程控制
在使用 Observable 进行异步编程时,我们需要掌握一些异步流程控制的方法。下面是一些常用的控制方法及其用法。
操作符 takeUntil
takeUntil 操作符可以让我们在某个条件成立时,终止一个可观察对象的执行:
-- -------------------- ---- ------- ------ - -------- - ---- ------- ------ - --------- - ---- ----------------- ----- ------ - --------------- ----- --------- - --- --------------- -- - ------------- -- - ---------- -- ------ --- ------ --------------------------------- -------------- -- ------------------
以上代码中,interval 操作符会每隔 1 秒钟产生一个数值,并将这些数值作为可观察对象。同时我们创建了一个 Promise,使得在 5 秒钟后 Promise 执行后,takeUntil 操作符就会打断该可观察对象。在此之后,就不会再产生任何数值。
操作符 debounceTime
使用 debounceTime 操作符可以让我们在指定的时间内限制可观察对象中产生的数据量,在用户输入等场景下非常实用:
-- -------------------- ---- ------- ------ - --------- - ---- ------- ------ - ------------ - ---- ----------------- ----- ----------- - ---------------------------------- ----- ------------ - ---------------------- -------- -------------------------- -------------------------- -- - ------------------------------- ---
以上代码中,fromEvent 操作符会在 search 元素的 input 事件上产生一个可观察对象,我们使用 debounceTime 操作符将产生的数据限制在了 1 秒钟内,以避免搜索频繁地进行请求。
结论
ES7 中引入的 Observable 作为异步解决方案,在一些较为复杂的异步场景下,相较于 Promise 具有更大的优势和潜力。在使用 Observable 时,我们需要注意异步流程控制的方法,并结合实际场景灵活运用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/66efe85e6fbf9601973145ed