所以我已经读到,在一些即将推出的JavaScript MVC中,observables正在寻求超越承诺:
观察与承诺之间有什么区别?
更新:道歉!删除了我的虚假陈述。
答案 0 :(得分:35)
承诺是未来价值的代表。 可观察量是可能无限量的值的表示。
Promise会在创建后立即触发获取该值。 Observable只会在您订阅它们时开始生成值。 (除非它是一个热门的观察者,但这超出了这个问题的范围)
Promise旨在表示AJAX调用。 Observable旨在表示任何事物:事件,来自数据库的数据,来自ajax调用的数据,(可能是无限的)序列等。
答案 1 :(得分:33)
观察与承诺之间有什么区别?
简单地说:一个promise以异步方式解析为单个值,一个observable异步解析(或发出)多个值(随着时间的推移)。
具体例子:
可在此处找到更多信息:http://reactivex.io/intro.html
我读过,观察者正在寻求超越承诺
不太可能。对于某些问题,Observable可能是更好的解决方案,但这并不能使承诺过时(如果这就是你的意思)。
答案 2 :(得分:24)
Promise提供了一种非常简单的回调机制,其中Rx提供了对异步编程的强大抽象。 Observable表示数据流,然后我们可以应用运算符来定义如何处理传入数据。
如果您只需要发出HTTP请求然后更新UI组件,那么使用Promise就足够了。
但是,大多数应用程序往往需要比这更复杂的需求(即使它在第一个时并不明显)。以我们的HTTP请求为例,让我们看看如何将其建模为Observable并使用一些Rx运算符可以帮助我们:
- 如果HTTP请求是由用户操作触发的,我们可能需要警惕触发多个HTTP请求(假设用户在搜索框中键入内容)。我们不想针对每次击键发出请求,因此我们可能希望 Throttle 我们的搜索,这样我们只会在用户停止输入300ms时触发请求。此外,如果用户键入一个单词,等待300毫秒,并添加另一个字符,我们将触发后续的HTTP请求。有了Promise,我们可能会遇到竞争条件,因为我们无法控制我们收到回复的顺序,也无法取消旧的请求。 Rx解决了这个问题,允许我们在流之间切换,在我们不再关心的旧请求订阅上调用 Dispose 。我们也可能过滤掉任何无效的搜索输入,例如其中搜索字词的长度少于3个字符。
- 支持处理超时/错误处理。假设我们的HTTP请求失败,Rx允许我们轻松重试发出请求。
- 说我们的应用程序的几个部分需要进行相同的HTTP调用,我们可能不希望实际多次调用。我们可以将我们的observable暴露给多个消费者,并使用重播来确保调用一次,并为后续订阅者缓存结果。我们甚至可以为Replay提供TimeSpan,为我们提供过期的缓存行为。
- 通过使用调度程序对线程进行强大的抽象,这允许我们控制并发性。更好的是,我们可以在单元测试中使用测试调度程序来控制时间,允许我们模拟超时,竞争条件等。
这些是一些快速示例,用于演示可能的内容。 Rx框架中有许多运算符可以满足所有类型的场景,Rx的可组合性意味着您可以轻松地组合运算符来定义所需的行为。创建自己的可重用运算符也很容易(例如RetryAfterDelay)。
总之,Rx可以做的事情比Promise可以做的更多,而且远远更多。我怀疑在接下来的几年里会继续转向Rx而不是Promises。
如需进一步阅读,我建议您查看Angular 2 guide中有关Observables的部分。
答案 3 :(得分:7)
当您想要获取单个数据块时,转换为Promise通常是一个不错的选择。所以当你收到数据时,你已经完成了。
但在某些情况下,请求始终只执行一次。您可以在服务器启动之前启动一个请求,取消它并发出不同的请求 回应了第一个请求。
例如在搜索组件中当用户在搜索框中键入名称时,您将通过该搜索查询重复发出HTTP请求。
请求 - 取消 - 新请求序列很难实现 承诺,但Observables很容易。
因此,如果您的组件仅使用一个请求获取数据,则使用Promise
是一个不错的选择,但如果它有一系列请求 - 取消 - 新请求,则应使用observable
答案 4 :(得分:1)
通常将可观察量与承诺进行比较。以下是一些主要差异:
可观察者是陈述性的;计算直到订阅才开始。 Promise在创建时立即执行。这使得observable对于定义可以在需要结果时运行的配方非常有用。
Observables提供了许多值。承诺提供一个。这使得observable可用于随时间获取多个值。
Observable区分链接和订阅。 Promise只有.then()子句。这使得observable对于创建系统其他部分使用的复杂转换配方非常有用,而不会导致工作被执行。
Observables subscribe()负责处理错误。承诺将错误推向孩子的承诺。这使得observable对集中和可预测的错误处理很有用。
官方网站上有角度的最佳解释:
答案 5 :(得分:1)
可观察VS。诺言(Jeremy Vilken)
除新语法外, observables 是JavaScript应用程序的一种新模式,可用于 管理异步活动。它们也是以JavaScript语言本机实现的功能的草稿,因此该功能的重要性在于模式。 RxJS是 库,我们将使用它来帮助我们在应用程序中实现可观察性。
承诺是帮助处理异步调用的另一种结构,这很有用 例如,用于发出API请求。承诺的主要限制在于 仅在一个呼叫周期内有用。例如,如果您希望有一个承诺,请返回 诸如用户点击之类的事件的价值,则承诺将在首次点击时解决。但是您可能会对处理每个用户的点击操作感兴趣。通常,您会使用一个事件 侦听器,它使您可以随着时间处理事件。这是一个重要的区别:可观察对象就像事件处理程序一样,它们继续通过 时间并允许您持续处理该数据流。
答案 6 :(得分:0)
正确理解Observable
时,与Promise
的区别非常明显。
使一个复杂的概念变得神秘的最好方法是从头开始实施它。这是一个几乎纯粹的功能Observable
实现和一个示例,不适用于Promise
s:
/*** Observable type ***/
// type constructor (of a product type)
const proType = name => cons => {
const f = (k, ...args) =>
Object.defineProperties({["run" + name]: k}, {
[Symbol.toStringTag]: {value: name},
[Symbol("args")]: {value: args}
});
return cons(f);
};
// value constructor
const Observable = proType("Observable")
(Observable => k => Observable(k));
/*** Observer factory ***/
const Observer = observer => {
let isUnsubscribed = false;
return {
next: function(x) {
if (isUnsubscribed)
throw new Error("unsubscribed");
else {
try {
return observer.next(x);
}
catch(e) {
isUnsubscribed = true;
this.cancel();
throw e;
}
}
},
error: function(e) {
if (isUnsubscribed)
throw new Error("unsubscribed");
else {
try {
return observer.error(e);
}
catch(e_) {
isUnsubscribed = true;
this.cancel();
throw e_;
}
}
},
complete: function() {
if (isUnsubscribed)
throw new Error("unsubscribed");
else {
try {
const r = observer.complete();
this.cancel();
return r;
}
catch(e) {
isUnsubscribed = true;
cancel();
throw e;
}
}
}
};
};
/*** combinators + auxiliary functions ***/
const subscribe = observable => handlers => {
const observer = Observer(handlers),
cancel = observable.runObservable(observer);
observer.cancel = cancel;
return cancel;
};
const obsMap = f => observable =>
Observable(observer => {
const mapObserver = {
next: x => observer.next(f(x)),
error: e => observer.error(e),
complete: () => observer.complete()
};
return observable.runObservable(mapObserver);
});
/*** main ***/
// create an Observable instance
const numStream = Observable(observer => {
let i = 0;
const timer = setInterval(() => {
observer.next(i++);
}, 1000);
return () => clearTimeout(timer);
});
// map a function over it
const squaredNumStream =
obsMap(x => x * x) (numStream);
// run the observable
const cancel = subscribe(squaredNumStream) ({
next: x => console.log(x),
error: e => console.error(e),
complete: () => console.log("finished")
});
// cancel it
setTimeout(cancel, 11000);
在上面的示例中,Observable
squaredNumStream
异步地发出理论上无限值的流。您无法使用Promise
来做到这一点,因为它们代表了一个单一的未来价值。
我本可以很容易地订阅另一个squaredNumStream
,而不会导致两个实例相互干扰。这是因为Observable
是单播的,而Promise
是多播的。
squaredNumStream
不在声明时运行,而是仅在订阅后运行,因为Observable
的计算是延迟的。另一方面,Promise
会受到急切的评估,也就是说,它们一创建就开始运行。
最后,Observable
可以通过设计取消,而Promise
则由于存在单播语义而难以取消。