让我们从承诺开始
在 Javascript 中,Promises 是一种用于优雅地处理异步代码的常见模式。如果您不知道什么是承诺,请从这里开始。它们看起来像这样:
todoService.getTodos() // this could be any async workload
.then(todos => {
// got returned todos
})
.catch(err => {
// error happened
})
重要部分:
todoService.getTodos() // returns a Promise
让我们暂时忘记getTodos() 的工作原理。需要知道的重要一点是,许多 libraries 支持 Promises,并且可以为 http 请求等异步工作负载返回 Promise。
一个 Promise 对象 implements 两个主要方法,可以轻松处理异步工作的结果。这些方法是.then() 和.catch()。 then 处理“成功”结果,catch 是错误处理程序。当then 处理程序返回数据时,这称为resolving 一个promise,当它向catch 处理程序抛出错误时,这称为rejecting。
.then(todos => { // promise resolved with successful results })
.catch(err => { // promise rejected with an error })
很酷的是,then 和 catch 还返回承诺,因此您可以像这样链接它们:
.then(todos => {
return todos[0]; // get first todo
})
.then(firstTodo => {
// got first todo!
})
这里有一个问题:承诺只能解决或拒绝一次
这对于像 http 请求这样的事情没问题,因为 http 请求基本上执行一次并返回一次(成功或错误)。
如果您想要一种优雅的方式流式传输异步数据,会发生什么?想想视频、音频、实时排行榜数据、聊天室消息。如果能够使用 Promise 设置一个处理程序,在数据流入时不断接受数据,那就太好了:
// impossible because promises only fire once!
videoService.streamVideo()
.then(videoChunk => { // new streaming chunk })
欢迎使用响应式模式
简而言之:Promise 用于异步单个请求,Observable 用于异步流数据。
看起来像这样:
videoService.getVideoStream() // returns observable, not promise
.subscribe(chunk => { // subscribe to an observable
// new chunk
}, err => {
// error thrown
});
看起来类似于承诺模式,对吧?可观察对象和承诺之间的一个主要区别。 Observables 将数据“发射”到“订阅”中,而不是使用单一使用的 .then() 和 .catch() 处理程序。
Angular 的 http 客户端库默认返回 observables,即使您可能认为 http 更适合单次使用承诺模式。但是关于响应式编程(如 rxJS)的一个很酷的事情是,您可以从其他事物(如点击事件或任何任意事件流)中生成可观察对象。然后,您可以将这些流组合在一起来做一些非常酷的事情。
例如,如果您想在每次点击刷新按钮并且每 60 秒刷新一次数据时,您可以设置如下内容:
const refreshObservable = someService.refreshButtonClicked(); // observable for every time the refresh button gets clicked
const timerObservable = someService.secondsTimer(60); // observable to fire every 60 seconds
merge(
refreshObservable,
timerObservable
)
.pipe(
refreshData()
)
.subscribe(data => // will keep firing with updated data! )
处理复杂过程的一种非常优雅的方式!反应式编程是一个相当大的话题,但this 是一个很好的工具,可以尝试和可视化所有有用的方法,你可以使用 observables 来编写很酷的东西。
注意:这是未经测试的伪代码,仅用于说明目的