feat: 翻译完了 Observable 与 RxJS
This commit is contained in:
parent
e0fc873240
commit
935fdf30dc
|
@ -1,24 +1,47 @@
|
|||
# Observables compared to other techniques
|
||||
|
||||
# 可观察对象与其它技术的比较
|
||||
|
||||
You can often use observables instead of promises to deliver values asynchronously. Similarly, observables can take the place of event handlers. Finally, because observables deliver multiple values, you can use them where you might otherwise build and operate on arrays.
|
||||
|
||||
你可以经常使用可观察对象(Observable)而不是承诺(Promise)来异步传递值。
|
||||
类似的,可观察对象也可以取代事件处理器的位置。最后,由于可观察对象传递多个值,所以你可以在任何可能构建和操作数组的地方使用可观察对象。
|
||||
|
||||
Observables behave somewhat differently from the alternative techniques in each of these situations, but offer some significant advantages. Here are detailed comparisons of the differences.
|
||||
|
||||
在这些情况下,可观察对象的行为与其替代技术有一些差异,不过也提供了一些显著的优势。下面是对这些差异的详细比较。
|
||||
|
||||
## Observables compared to promises
|
||||
|
||||
## 可观察对象 vs. 承诺
|
||||
|
||||
Observables are often compared to promises. Here are some key differences:
|
||||
|
||||
可观察对象经常拿来和承诺进行对比。有一些关键的不同点:
|
||||
|
||||
* Observables are declarative; computation does not start until subscription. Promises execute immediately on creation. This makes observables useful for defining recipes that can be run whenever you need the result.
|
||||
|
||||
可观察对象是声明式的,在被订阅之前,它不会开始执行。承诺是在创建时就立即执行的。这让可观察对象可用于定义那些应该按需执行的菜谱。
|
||||
|
||||
* Observables provide many values. Promises provide one. This makes observables useful for getting multiple values over time.
|
||||
|
||||
可观察对象能提供多个值。承诺只提供一个。这让可观察对象可用于随着时间的推移获取多个值。
|
||||
|
||||
* Observables differentiate between chaining and subscription. Promises only have `.then()` clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.
|
||||
|
||||
可观察对象会区分串联处理和订阅语句。承诺只有 `.then()` 语句。这让可观察对象可用于创建供系统的其它部分使用而不希望立即执行的复杂菜谱。
|
||||
|
||||
* Observables `subscribe()` is responsible for handling errors. Promises push errors to the child promises. This makes observables useful for centralized and predictable error handling.
|
||||
|
||||
可观察对象的 `subscribe()` 会负责处理错误。承诺会把错误推送给它的子承诺。这让可观察对象可用于进行集中式、可预测的错误处理。
|
||||
|
||||
### Creation and subscription
|
||||
|
||||
* Observables are not executed until a consumer subcribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.
|
||||
### 创建与订阅
|
||||
|
||||
* Observables are not executed until a consumer subscribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.
|
||||
|
||||
在有消费者订阅之前,可观察对象不会执行。`subscribe()` 会执行一次定义好的行为,并且可以再次调用它。每次订阅都是单独计算的。重新订阅会导致重新计算这些值。
|
||||
|
||||
<code-example hideCopy>
|
||||
|
||||
|
@ -33,6 +56,8 @@ observable.subscribe(() => {
|
|||
|
||||
* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.
|
||||
|
||||
承诺会立即执行,并且只执行一次。当承诺创建时,会立即计算出结果。没有办法重新做一次。所有的 `then` 语句(订阅)都会共享同一次计算。
|
||||
|
||||
<code-example hideCopy>
|
||||
|
||||
// initiate execution
|
||||
|
@ -46,18 +71,28 @@ promise.then((value) => {
|
|||
|
||||
### Chaining
|
||||
|
||||
### 串联
|
||||
|
||||
* Observables differentiate between transformation function such as a map and subscription. Only subscription activates the subscriber function to start computing the values.
|
||||
|
||||
可观察对象会区分各种转换函数,比如映射和订阅。只有订阅才会激活订阅者函数,以开始计算那些值。
|
||||
|
||||
<code-example hideCopy>observable.map((v) => 2*v);</code-example>
|
||||
|
||||
* Promises do not differentiate between the last `.then` clauses (equivalent to subscription) and intermediate `.then` clauses (equivalent to map).
|
||||
|
||||
承诺并不区分最后的 `.then()` 语句(等价于订阅)和中间的 `.then()` 语句(等价于映射)。
|
||||
|
||||
<code-example hideCopy>promise.then((v) => 2*v);</code-example>
|
||||
|
||||
### Cancellation
|
||||
|
||||
### 可取消
|
||||
|
||||
* Observable subscriptions are cancellable. Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work.
|
||||
|
||||
可观察对象的订阅是可取消的。取消订阅会移除监听器,使其不再接受将来的值,并通知订阅者函数取消正在进行的工作。
|
||||
|
||||
<code-example hideCopy>
|
||||
|
||||
const sub = obs.subscribe(...);
|
||||
|
@ -67,12 +102,16 @@ sub.unsubscribe();
|
|||
|
||||
* Promises are not cancellable.
|
||||
|
||||
承诺是不可取消的。
|
||||
|
||||
### Error handling
|
||||
|
||||
### 错误处理
|
||||
|
||||
* Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable.
|
||||
|
||||
可观察对象的错误处理是交给订阅者的错误处理器的,并且该订阅者会自动取消对这个可观察对象的订阅。
|
||||
|
||||
<code-example hideCopy>
|
||||
|
||||
obs.subscribe(() => {
|
||||
|
@ -83,6 +122,8 @@ obs.subscribe(() => {
|
|||
|
||||
* Promises push errors to the child promises.
|
||||
|
||||
承诺会把错误推给其子承诺。
|
||||
|
||||
<code-example hideCopy>
|
||||
|
||||
promise.then(() => {
|
||||
|
@ -93,8 +134,12 @@ promise.then(() => {
|
|||
|
||||
### Cheat sheet
|
||||
|
||||
### 速查表
|
||||
|
||||
The following code snippets illustrate how the same kind of operation is defined using observables and promises.
|
||||
|
||||
下列代码片段揭示了同样的操作要如何分别使用可观察对象和承诺进行实现。
|
||||
|
||||
<table>
|
||||
|
||||
<th>
|
||||
|
@ -102,6 +147,8 @@ The following code snippets illustrate how the same kind of operation is defined
|
|||
<td>
|
||||
|
||||
Operation
|
||||
|
||||
操作
|
||||
|
||||
</td>
|
||||
|
||||
|
@ -109,12 +156,16 @@ The following code snippets illustrate how the same kind of operation is defined
|
|||
|
||||
Observable
|
||||
|
||||
可观察对象
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Promise
|
||||
|
||||
承诺
|
||||
|
||||
</td>
|
||||
|
||||
</th>
|
||||
|
@ -125,6 +176,8 @@ The following code snippets illustrate how the same kind of operation is defined
|
|||
|
||||
Creation
|
||||
|
||||
创建
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -151,6 +204,8 @@ The following code snippets illustrate how the same kind of operation is defined
|
|||
|
||||
Transform
|
||||
|
||||
转换
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -173,6 +228,8 @@ The following code snippets illustrate how the same kind of operation is defined
|
|||
|
||||
Subscribe
|
||||
|
||||
订阅
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -199,6 +256,8 @@ The following code snippets illustrate how the same kind of operation is defined
|
|||
|
||||
Unsubscribe
|
||||
|
||||
取消订阅
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -219,12 +278,20 @@ The following code snippets illustrate how the same kind of operation is defined
|
|||
|
||||
## Observables compared to events API
|
||||
|
||||
## 可观察对象 vs. 事件 API
|
||||
|
||||
Observables are very similar to event handlers that use the events API. Both techniques define notification handlers, and use them to process multiple values delivered over time. Subscribing to an observable is equivalent to adding an event listener. One significant difference is that you can configure an observable to transform an event before passing the event to the handler.
|
||||
|
||||
可观察对象和事件 API 中的事件处理器很像。这两种技术都会定义通知处理器,并使用它们来处理一段时间内传递的多个值。订阅可观察对象与添加事件处理器是等价的。一个显著的不同是你可以配置可观察对象,使其在把事件传给事件处理器之间先进行转换。
|
||||
|
||||
Using observables to handle events and asynchronous operations can have the advantage of greater consistency in contexts such as HTTP requests.
|
||||
|
||||
使用可观察对象来处理错误和异步操作在 HTTP 请求这样的场景下更加具有一致性。
|
||||
|
||||
Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API.
|
||||
|
||||
下列代码片段揭示了同样的操作要如何分别使用可观察对象和事件 API 进行实现。
|
||||
|
||||
<table>
|
||||
|
||||
<th>
|
||||
|
@ -233,12 +300,16 @@ Here are some code samples that illustrate how the same kind of operation is def
|
|||
|
||||
Observable
|
||||
|
||||
可观察对象
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Events API
|
||||
|
||||
事件 API
|
||||
|
||||
</td>
|
||||
|
||||
</th>
|
||||
|
@ -249,6 +320,8 @@ Here are some code samples that illustrate how the same kind of operation is def
|
|||
|
||||
Creation & cancellation
|
||||
|
||||
创建与取消
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -285,6 +358,8 @@ button.removeEventListener(‘click’, handler);
|
|||
|
||||
Subscription
|
||||
|
||||
订阅
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -311,6 +386,8 @@ button.removeEventListener(‘click’, handler);
|
|||
|
||||
Configuration
|
||||
|
||||
配置
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
@ -338,8 +415,13 @@ button.removeEventListener(‘click’, handler);
|
|||
|
||||
## Observables compared to arrays
|
||||
|
||||
## 可观察对象 vs. 数组
|
||||
|
||||
An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery.
|
||||
|
||||
可观察对象会随时间生成值。数组是用一组静态的值创建的。某种意义上,可观察对象是异步的,而数组是同步的。
|
||||
在下列例子中,➞ 符号表示异步传递值。
|
||||
|
||||
<table>
|
||||
|
||||
<th>
|
||||
|
@ -348,12 +430,16 @@ An observable produces values over time. An array is created as a static set of
|
|||
|
||||
Observable
|
||||
|
||||
可观察对象
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
Array
|
||||
|
||||
数组
|
||||
|
||||
</td>
|
||||
|
||||
</th>
|
||||
|
@ -364,6 +450,8 @@ An observable produces values over time. An array is created as a static set of
|
|||
|
||||
Given
|
||||
|
||||
给出值
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
|
|
@ -1,43 +1,77 @@
|
|||
# Observables in Angular
|
||||
|
||||
# Angular 中的可观察对象
|
||||
|
||||
Angular makes use of observables as an interface to handle a variety of common asynchronous operations. For example:
|
||||
|
||||
Angular 使用可观察对象作为处理各种常用异步操作的接口。比如:
|
||||
|
||||
* The `EventEmitter` class extends `Observable`.
|
||||
|
||||
`EventEmitter` 类派生自 `Observable`。
|
||||
|
||||
* The HTTP module uses observables to handle AJAX requests and responses.
|
||||
|
||||
HTTP 模块使用可观察对象来处理 AJAX 请求和响应。
|
||||
|
||||
* The Router and Forms modules use observables to listen for and respond to user-input events.
|
||||
|
||||
路由器和表单模块使用可观察对象来监听对用户输入事件的响应。
|
||||
|
||||
## Event emitter
|
||||
|
||||
## 事件发送器 `EventEmitter`
|
||||
|
||||
Angular provides an `EventEmitter` class that is used when publishing values from a component through the `@Output()` decorator. `EventEmitter` extends `Observable`, adding an `emit()` method so it can send arbitrary values. When you call `emit()`, it passes the emitted value to the `next()` method of any subscribed observer.
|
||||
|
||||
Angular 提供了一个 `EventEmitter` 类,它用来从组件的 `@Output()` 属性中发布一些值。`EventEmitter` 扩展了 `Observable`,并添加了一个 `emit()` 方法,这样它就可以发送任意值了。当你调用 `emit()` 时,就会把所发送的值传给订阅上来的观察者的 `next()` 方法。
|
||||
|
||||
A good example of usage can be found on the [EventEmitter](https://angular.io/api/core/EventEmitter) documentation. Here is the example component that listens for open and close events:
|
||||
|
||||
这种用法的例子参见 [EventEmitter](https://angular.cn/api/core/EventEmitter) 文档。下面这个范例组件监听了 `open` 和 `close` 事件:
|
||||
|
||||
`<zippy (open)="onOpen($event)" (close)="onClose($event)"></zippy>`
|
||||
|
||||
Here is the component definition:
|
||||
|
||||
组件的定义如下:
|
||||
|
||||
<code-example path="observables-in-angular/src/main.ts" title="EventEmitter" region="eventemitter"></code-example>
|
||||
|
||||
## HTTP
|
||||
|
||||
Angular’s `HttpClient` returns observables from HTTP method calls. For instance, `http.get(‘/api’)` returns an observable. This provides several advantages over promise-based HTTP APIs:
|
||||
|
||||
Angular 的 `HttpClient` 从 HTTP 方法调用中返回了可观察对象。例如,`http.get(‘/api’)` 就会返回可观察对象。相对于基于承诺(Promise)的 HTTP API,它有一系列优点:
|
||||
|
||||
* Observables do not mutate the server response (as can occur through chained `.then()` calls on promises). Instead, you can use a series of operators to transform values as needed.
|
||||
|
||||
可观察对象不会修改服务器的响应(和在承诺上串联起来的 `.then()` 调用一样)。反之,你可以使用一系列操作符来按需转换这些值。
|
||||
|
||||
* HTTP requests are cancellable through the `unsubscribe()` method.
|
||||
|
||||
HTTP 请求是可以通过 `unsubscribe()` 方法来取消的。
|
||||
|
||||
* Requests can be configured to get progress event updates.
|
||||
|
||||
请求可以进行配置,以获取进度事件的变化。
|
||||
|
||||
* Failed requests can be retried easily.
|
||||
|
||||
失败的请求很容易重试。
|
||||
|
||||
## Async pipe
|
||||
|
||||
## Async 管道
|
||||
|
||||
The [AsyncPipe](https://angular.io/api/common/AsyncPipe) subscribes to an observable or promise and returns the latest value it has emitted. When a new value is emitted, the pipe marks the component to be checked for changes.
|
||||
|
||||
[AsyncPipe](https://angular.io/api/common/AsyncPipe) 会订阅一个可观察对象或承诺,并返回其发出的最后一个值。当发出新值时,该管道就会把这个组件标记为需要进行变更检查的(译注:因此可能导致刷新界面)。
|
||||
|
||||
The following example binds the `time` observable to the component's view. The observable continuously updates the view with the current time.
|
||||
|
||||
下面的例子把 `time` 这个可观察对象绑定到了组件的视图中。这个可观察对象会不断使用当前时间更新组件的视图。
|
||||
|
||||
<code-example path="observables-in-angular/src/main.ts" title="Using async pipe" region="pipe"></code-example>
|
||||
|
||||
## Router
|
||||
|
@ -46,10 +80,16 @@ The following example binds the `time` observable to the component's view. The o
|
|||
|
||||
[`Router.events`](https://angular.io/api/router/Router#events) provides events as observables. You can use the `filter()` operator from RxJS to look for events of interest, and subscribe to them in order to make decisions based on the sequence of events in the navigation process. Here's an example:
|
||||
|
||||
[`Router.events`](https://angular.io/api/router/Router#events) 以可观察对象的形式提供了其事件。
|
||||
你可以使用 RxJS 中的 `filter()` 操作符来找到感兴趣的事件,并且订阅它们,以便根据浏览过程中产生的事件序列作出决定。
|
||||
例子如下:
|
||||
|
||||
<code-example path="observables-in-angular/src/main.ts" title="Router events" region="router"></code-example>
|
||||
|
||||
The [ActivatedRoute](https://angular.io/api/router/ActivatedRoute) is an injected router service that makes use of observables to get information about a route path and parameters. For example, `ActivateRoute.url` contains an observable that reports the route path or paths. Here's an example:
|
||||
|
||||
[ActivatedRoute](https://angular.io/api/router/ActivatedRoute) 是一个可注入的路由器服务,它使用可观察对象来获取关于路由路径和路由参数的信息。比如,`ActivateRoute.url` 包含一个用于汇报路由路径的可观察对象。例子如下:
|
||||
|
||||
<code-example path="observables-in-angular/src/main.ts" title="ActivatedRoute" region="activated_route"></code-example>
|
||||
|
||||
## Reactive forms
|
||||
|
@ -58,4 +98,7 @@ The [ActivatedRoute](https://angular.io/api/router/ActivatedRoute) is an injecte
|
|||
|
||||
Reactive forms have properties that use observables to monitor form control values. The [`FormControl`](https://angular.io/api/forms/FormControl) properties `valueChanges` and `statusChanges` contain observables that raise change events. Subscribing to an observable form-control property is a way of triggering application logic within the component class. For example:
|
||||
|
||||
响应式表单具有一些属性,它们使用可观察对象来监听表单控件的值。
|
||||
[`FormControl`](https://angular.io/api/forms/FormControl) 的 `valueChanges` 属性和 `statusChanges` 属性包含了会发出变更事件的可观察对象。订阅可观察的表单控件属性是在组件类中触发应用逻辑的途径之一。比如:
|
||||
|
||||
<code-example path="observables-in-angular/src/main.ts" title="Reactive forms" region="forms"></code-example>
|
||||
|
|
|
@ -1,51 +1,97 @@
|
|||
# Observables
|
||||
|
||||
# 可观察对象(Observable)
|
||||
|
||||
Observables provide support for passing messages between publishers and subscribers in your application. Observables offer significant benefits over other techniques for event handling, asynchronous programming, and handling multiple values.
|
||||
|
||||
可观察对象支持在应用中的发布者和订阅者之间传递消息。
|
||||
在需要进行事件处理、异步编程和处理多个值的时候,可观察对象相对其它技术有着显著的优点。
|
||||
|
||||
Observables are declarative—that is, you define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes, or until they unsubscribe.
|
||||
|
||||
可观察对象是声明式的 —— 也就是说,虽然你定义了一个用于发布值的函数,但是在有消费者订阅它之前,这个函数并不会实际执行。
|
||||
订阅之后,当这个函数执行完或取消订阅时,订阅者就会收到通知。
|
||||
|
||||
An observable can deliver multiple values of any type—literals, messages, or events, depending on the context. The API for receiving values is the same whether the values are delivered synchronously or asynchronously. Because setup and teardown logic are both handled by the observable, your application code only needs to worry about subscribing to consume values, and when done, unsubscribing. Whether the stream was keystrokes, an HTTP response, or an interval timer, the interface for listening to values and stopping listening is the same.
|
||||
|
||||
可观察对象可以发送多个任意类型的值 —— 字面量、消息、事件。无论这些值是同步发送的还是异步发送的,接收这些值的 API 都是一样的。
|
||||
由于准备(setup)和清场(teardown)的逻辑都是由可观察对象自己处理的,因此你的应用代码只管订阅并消费这些值就可以了,做完之后,取消订阅。无论这个流是击键流、HTTP 响应流还是定时器,对这些值进行监听和停止监听的接口都是一样的。
|
||||
|
||||
Because of these advantages, observables are used extensively within Angular, and are recommended for app development as well.
|
||||
|
||||
由于这些优点,可观察对象在 Angular 中得到广泛使用,我们也同样建议应用开发者好好使用它。
|
||||
|
||||
## Basic usage and terms
|
||||
|
||||
## 基本用法和词汇
|
||||
|
||||
As a publisher, you create an `Observable` instance that defines a *subscriber* function. This is the function that is executed when a consumer calls the `subscribe()` method. The subscriber function defines how to obtain or generate values or messages to be published.
|
||||
|
||||
作为发布者,你创建一个 `Observable` 的实例,其中定义了一个*订阅者(subscriber)*函数。
|
||||
当有消费者调用 `subscribe()` 方法时,这个函数就会执行。
|
||||
订阅者函数用于定义“如何获取或生成那些要发布的值或消息”。
|
||||
|
||||
To execute the observable you have created and begin receiving notifications, you call its `subscribe()` method, passing an *observer*. This is a JavaScript object that defines the handlers for the notifications you receive. The `subscribe()` call returns a `Subscription` object that has an `unsubscribe()` method, which you call to stop receiving notifications.
|
||||
|
||||
要执行所创建的可观察对象,并开始从中接收通知,你就要调用它的 `subscribe()` 方法,并传入一个*观察者(observer)*。
|
||||
这是一个 JavaScript 对象,它定义了你收到的这些消息的处理器(handler)。
|
||||
`subscribe()` 调用会返回一个 `Subscription` 对象,该对象具有一个 `unsubscribe()` 方法。
|
||||
当调用该方法时,你就会停止接收通知。
|
||||
|
||||
Here's an example that demonstrates the basic usage model by showing how an observable could be used to provide geolocation updates.
|
||||
|
||||
下面这个例子中示范了这种基本用法,它展示了如何使用可观察对象来对当前地理位置进行更新。
|
||||
|
||||
<code-example path="observables/src/geolocation.ts" title="Observe geolocation updates"></code-example>
|
||||
|
||||
## Defining observers
|
||||
|
||||
## 定义观察者
|
||||
|
||||
A handler for receiving observable notifications implements the `Observer` interface. It is an object that defines callback methods to handle the three types of notifications that an observable can send:
|
||||
|
||||
| Notification type | Description |
|
||||
用于接收可观察对象通知的处理器要实现 `Observer` 接口。这个对象定义了一些回调函数来处理可观察对象可能会发来的三种通知:
|
||||
|
||||
| <p>Notification type</p><p>通知类型</p> | <p>Description</p><p>说明</p> |
|
||||
|:---------|:-------------------------------------------|
|
||||
| `next` | Required. A handler for each delivered value. Called zero or more times after execution starts.|
|
||||
| `error` | Optional. A handler for an error notification. An error halts execution of the observable instance.|
|
||||
| `complete` | Optional. A handler for the execution-complete notification. Delayed values can continue to be delivered to the next handler after execution is complete.|
|
||||
| `next` | <p>Required. A handler for each delivered value. Called zero or more times after execution starts.</p><p>必要。用来处理每个送达值。在开始执行后可能执行零次或多次。</p>|
|
||||
| `error` | <p>Optional. A handler for an error notification. An error halts execution of the observable instance.</p><p> 可选。用来处理错误通知。错误会中断这个可观察对象实例的执行过程。 </p>|
|
||||
| `complete` | <p>Optional. A handler for the execution-complete notification. Delayed values can continue to be delivered to the next handler after execution is complete.</p><p> 可选。用来处理执行完毕(complete)通知。当执行完毕后,这些值就会继续传给下一个处理器。 </p>|
|
||||
|
||||
An observer object can define any combination of these handlers. If you don't supply a handler for a notification type, the observer ignores notifications of that type.
|
||||
|
||||
观察者对象可以定义这三种处理器的任意组合。如果你不为某种通知类型提供处理器,这个观察者就会忽略相应类型的通知。
|
||||
|
||||
## Subscribing
|
||||
|
||||
## 订阅
|
||||
|
||||
An `Observable` instance begins publishing values only when someone subscribes to it. You subscribe by calling the `subscribe()` method of the instance, passing an observer object to receive the notifications.
|
||||
|
||||
只有当有人订阅 `Observable` 的实例时,它才会开始发布值。
|
||||
订阅时要先调用该实例的 `subscribe()` 方法,并把一个观察者对象传给它,用来接收通知。
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
In order to show how subscribing works, we need to create a new observable. There is a constructor that you use to create new instances, but for illustration, we can use some static methods on the `Observable` class that create simple observables of frequently used types:
|
||||
|
||||
为了展示订阅的原理,我们需要创建新的可观察对象。它有一个构造函数可以用来创建新实例,但是为了更简明,也可以使用 `Observable` 上定义的一些静态方法来创建一些常用的简单可观察对象:
|
||||
|
||||
* `Observable.of(...items)`—Returns an `Observable` instance that synchronously delivers the values provided as arguments.
|
||||
|
||||
`Observable.of(...items)` —— 返回一个 `Observable` 实例,它用同步的方式把参数中提供的这些值发送出来。
|
||||
|
||||
* `Observable.from(iterable)`—Converts its argument to an `Observable` instance. This method is commonly used to convert an array to an observable.
|
||||
|
||||
`Observable.from(iterable)` —— 把它的参数转换成一个 `Observable` 实例。
|
||||
该方法通常用于把一个数组转换成一个(发送多个值的)可观察对象。
|
||||
|
||||
</div>
|
||||
|
||||
Here's an example of creating and subscribing to a simple observable, with an observer that logs the received message to the console:
|
||||
|
||||
下面的例子会创建并订阅一个简单的可观察对象,它的观察者会把接收到的消息记录到控制台中:
|
||||
|
||||
<code-example
|
||||
path="observables/src/subscribing.ts"
|
||||
region="observer"
|
||||
|
@ -53,54 +99,92 @@ Here's an example of creating and subscribing to a simple observable, with an ob
|
|||
|
||||
Alternatively, the `subscribe()` method can accept callback function definitions in line, for `next`, `error`, and `complete` handlers. For example, the following `subscribe()` call is the same as the one that specifies the predefined observer:
|
||||
|
||||
另外,`subscribe()` 方法还可以接收定义在同一行中的回调函数,无论 `next`、`error` 还是 `complete` 处理器。比如,下面的 `subscribe()` 调用和前面指定预定义观察者的例子是等价的。
|
||||
|
||||
<code-example path="observables/src/subscribing.ts" region="sub_fn" title="Subscribe with positional arguments"></code-example>
|
||||
|
||||
In either case, a `next` handler is required. The `error` and `complete` handlers are optional.
|
||||
|
||||
Note that a `next()` function could receive, for instance, message strings, or event objects, numeric values, or stuctures, depending on context. As a general term, we refer to data published by an observable as a *stream*. Any type of value can be represented with an observable, and the values are published as a stream.
|
||||
无论哪种情况,`next` 处理器都是必要的,而 `error` 和 `complete` 处理器是可选的。
|
||||
|
||||
Note that a `next()` function could receive, for instance, message strings, or event objects, numeric values, or structures, depending on context. As a general term, we refer to data published by an observable as a *stream*. Any type of value can be represented with an observable, and the values are published as a stream.
|
||||
|
||||
注意,`next()` 函数可以接受消息字符串、事件对象、数字值或各种结构,具体类型取决于上下文。
|
||||
为了更通用一点,我们把由可观察对象发布出来的数据统称为*流*。任何类型的值都可以表示为可观察对象,而这些值会被发布为一个流。
|
||||
|
||||
## Creating observables
|
||||
|
||||
## 创建可观察对象
|
||||
|
||||
Use the `Observable` constructor to create an observable stream of any type. The constructor takes as its argument the subscriber function to run when the observable’s `subscribe()` method executes. A subscriber function receives an `Observer` object, and can publish values to the observer's `next()` method.
|
||||
|
||||
使用 `Observable` 构造函数可以创建任何类型的可观察流。
|
||||
当执行可观察对象的 `subscribe()` 方法时,这个构造函数就会把它接收到的参数作为订阅函数来运行。
|
||||
订阅函数会接收一个 `Observer` 对象,并把值发布给观察者的 `next()` 方法。
|
||||
|
||||
For example, to create an observable equivalent to the `Observable.of(1, 2, 3)` above, you could do something like this:
|
||||
|
||||
比如,要创建一个与前面的 `Observable.of(1, 2, 3)` 等价的可观察对象,你可以这样做:
|
||||
|
||||
<code-example path="observables/src/creating.ts" region="subscriber" title="Create observable with constructor"></code-example>
|
||||
|
||||
To take this example a little further, we can create an observable that publishes events. In this example, the subscriber function is defined inline.
|
||||
|
||||
如果要略微加强这个例子,我们可以创建一个用来发布事件的可观察对象。在这个例子中,订阅函数是用内联方式定义的。
|
||||
|
||||
<code-example path="observables/src/creating.ts" region="fromevent" title="Create with custom fromEvent function"></code-example>
|
||||
|
||||
Now you can use this function to create an observable that publishes keydown events:
|
||||
|
||||
现在,你就可以使用这个函数来创建可发布 `keydown` 事件的可观察对象了:
|
||||
|
||||
<code-example path="observables/src/creating.ts" region="fromevent_use" title="Use custom fromEvent function"></code-example>
|
||||
|
||||
## Multicasting
|
||||
|
||||
## 多播
|
||||
|
||||
A typical observable creates a new, independent execution for each subscribed observer. When an observer subscribes, the observable wires up an event handler and delivers values to that observer. When a second observer subscribes, the observable then wires up a new event handler and delivers values to that second observer in a separate execution.
|
||||
|
||||
典型的可观察对象会为每一个观察者创建一次新的、独立的执行。
|
||||
当观察者进行订阅时,该可观察对象会连上一个事件处理器,并且向那个观察者发送一些值。当第二个观察者订阅时,这个可观察对象就会连上一个新的事件处理器,并独立执行一次,把这些值发送给第二个可观察对象。
|
||||
|
||||
Sometimes, instead of starting an independent execution for each subscriber, you want each subscription to get the same values—even if values have already started emitting. This might be the case with something like an observable of clicks on the document object.
|
||||
|
||||
有时候,我们不想对每一个订阅者都独立执行一次,你可能会希望每次订阅都得到同一批值 —— 即使是那些你已经发送过的。这在某些情况下有用,比如用来发送 `document` 上的点击事件的可观察对象。
|
||||
|
||||
*Multicasting* is the practice of broadcasting to a list of multiple subscribers in a single execution. With a multicasting observable, you don't register multiple listeners on the document, but instead re-use the first listener and send values out to each subscriber.
|
||||
|
||||
*多播*用来让可观察对象在一次执行中同时广播给多个订阅者。借助支持多播的可观察对象,你不必注册多个监听器,而是复用第一个(`next`)监听器,并且把值发送给各个订阅者。
|
||||
|
||||
When creating an observable you should determine how you want that observable to be used and whether or not you want to multicast its values.
|
||||
|
||||
当创建可观察对象时,你要决定你希望别人怎么用这个对象以及是否对它的值进行多播。
|
||||
|
||||
Let’s look at an example that counts from 1 to 3, with a one-second delay after each number emitted.
|
||||
|
||||
我们来看一个从 1 到 3 进行计数的例子,它每发出一个数字就会等待 1 秒。
|
||||
|
||||
<code-example path="observables/src/multicasting.ts" region="delay_sequence" title="Create a delayed sequence"></code-example>
|
||||
|
||||
Notice that if you subscribe twice, there will be two separate streams, each emitting values every second. It looks something like this:
|
||||
|
||||
注意,如果你订阅了两次,就会有两个独立的流,每个流都会每秒发出一个数字。代码如下:
|
||||
|
||||
<code-example path="observables/src/multicasting.ts" region="subscribe_twice" title="Two subscriptions"></code-example>
|
||||
|
||||
Changing the observable to be multicasting could look something like this:
|
||||
|
||||
修改这个可观察对象以支持多播,代码如下:
|
||||
|
||||
<code-example path="observables/src/multicasting.ts" region="multicast_sequence" title="Create a multicast subscriber"></code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
Multicasting observables take a bit more setup, but they can be useful for certain applications. Later we will look at tools that simplify the process of multicasting, allowing you to take any observable and make it multicasting.
|
||||
|
||||
虽然支持多播的可观察对象需要做更多的准备工作,但对某些应用来说,这非常有用。稍后我们会介绍一些简化多播的工具,它们让你能接收任何可观察对象,并把它变成支持多播的。
|
||||
|
||||
</div>
|
||||
|
||||
## Error handling
|
||||
|
@ -109,6 +193,8 @@ Notice that if you subscribe twice, there will be two separate streams, each emi
|
|||
|
||||
Because observables produce values asynchronously, try/catch will not effectively catch errors. Instead, you handle errors by specifying an `error` callback on the observer. Producing an error also causes the observable to clean up subscriptions and stop producing values. An observable can either produce values (calling the `next` callback), or it can complete, calling either the `complete` or `error` callback.
|
||||
|
||||
由于可观察对象会异步生成值,所以用 `try/catch` 是无法捕获错误的。你应该在观察者中指定一个 `error` 回调来处理错误。发生错误时还会导致可观察对象清理现有的订阅,并且停止生成值。可观察对象可以生成值(调用 `next` 回调),也可以调用 `complete` 或 `error` 回调来主动结束。
|
||||
|
||||
<code-example>
|
||||
|
||||
myObservable.subscribe({
|
||||
|
@ -119,3 +205,5 @@ myObservable.subscribe({
|
|||
</code-example>
|
||||
|
||||
Error handling (and specifically recovering from an error) is covered in more detail in a later section.
|
||||
|
||||
在稍后的小节中会对错误处理(特别是从错误中的恢复)做更详细的讲解。
|
||||
|
|
|
@ -1,27 +1,52 @@
|
|||
# Practical observable usage
|
||||
|
||||
# 可观察对象用法实战
|
||||
|
||||
Here are some examples of domains in which observables are particularly useful.
|
||||
|
||||
这里示范了一些在某种领域中可观察对象会特别有用的例子。
|
||||
|
||||
## Type-ahead suggestions
|
||||
|
||||
## 输入提示(type-ahead)建议
|
||||
|
||||
Observables can simplify the implementation of type-ahead suggestions. Typically, a type-ahead has to do a series of separate tasks:
|
||||
|
||||
可观察对象可以简化输入提示建议的实现方式。典型的输入提示要完成一系列独立的任务:
|
||||
|
||||
* Listen for data from an input.
|
||||
|
||||
从输入中监听数据。
|
||||
|
||||
* Trim the value (remove whitespace) and make sure it’s a minimum length.
|
||||
|
||||
移除输入值前后的空白字符,并确认它达到了最小长度。
|
||||
|
||||
* Debounce (so as not to send off API requests for every keystroke, but instead wait for a break in keystrokes).
|
||||
|
||||
防抖(这样才能防止连续按键时每次按键都发起 API 请求,而应该等到按键出现停顿时才发起)
|
||||
|
||||
* Don’t send a request if the value stays the same (rapidly hit a character, then backspace, for instance).
|
||||
|
||||
如果输入值没有变化,则不要发起请求(比如按某个字符,然后快速按退格)。
|
||||
|
||||
* Cancel ongoing AJAX requests if their results will be invalidated by the updated results.
|
||||
|
||||
如果已发出的 AJAX 请求的结果会因为后续的修改而变得无效,那就取消它。
|
||||
|
||||
Writing this in full JavaScript can be quite involved. With observables, you can use a simple series of RxJS operators:
|
||||
|
||||
完全用 JavaScript 的传统写法实现这个功能可能需要大量的工作。使用可观察对象,你可以使用这样一个 RxJS 操作符的简单序列:
|
||||
|
||||
<code-example path="practical-observable-usage/src/typeahead.ts" title="Typeahead"></code-example>
|
||||
|
||||
## Exponential backoff
|
||||
|
||||
## 指数化退避
|
||||
|
||||
Exponential backoff is a technique in which you retry an API after failure, making the time in between retries longer after each consecutive failure, with a maximum number of retries after which the request is considered to have failed. This can be quite complex to implement with promises and other methods of tracking AJAX calls. With observables, it is very easy:
|
||||
|
||||
指数化退避是一种失败后重试 API 的技巧,它会在每次连续的失败之后让重试时间逐渐变长,超过最大重试次数之后就会彻底放弃。
|
||||
如果使用承诺和其它跟踪 AJAX 调用的方法会非常复杂,而使用可观察对象,这非常简单:
|
||||
|
||||
<code-example path="practical-observable-usage/src/backoff.ts" title="Exponential backoff"></code-example>
|
||||
|
|
|
@ -1,23 +1,43 @@
|
|||
# The RxJS library
|
||||
|
||||
# RxJS 库
|
||||
|
||||
Reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change ([Wikipedia](https://en.wikipedia.org/wiki/Reactive_programming)). RxJS (Reactive Extensions for JavaScript) is a library for reactive programming using observables that makes it easier to compose asynchronous or callback-based code ([RxJS Docs](http://reactivex.io/rxjs/)).
|
||||
|
||||
响应式编程是一种面向数据流和变更传播的异步编程范式([Wikipedia](https://zh.wikipedia.org/wiki/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B))。RxJS(响应式扩展的 JavaScript 版)是一个使用可观察对象进行响应式编程的库,它让组合异步代码和基于回调的代码变得更简单 ([RxJS Docs](http://reactivex.io/rxjs/))。
|
||||
|
||||
RxJS provides an implementation of the `Observable` type, which is needed until the type becomes part of the language and until browsers support it. The library also provides utility functions for creating and working with observables. These utility functions can be used for:
|
||||
|
||||
RxJS 提供了一种对 `Observable` 类型的实现,直到 `Observable` 成为了 JavaScript 语言的一部分并且浏览器支持它之前,它都是必要的。这个库还提供了一些工具函数,用于创建和使用可观察对象。这些工具函数可用于:
|
||||
|
||||
* Converting existing code for async operations into observables
|
||||
|
||||
把现有的异步代码转换成可观察对象
|
||||
|
||||
* Iterating through the values in a stream
|
||||
|
||||
迭代流中的各个值
|
||||
|
||||
* Mapping values to different types
|
||||
|
||||
把这些值映射成其它类型
|
||||
|
||||
* Filtering streams
|
||||
|
||||
对流进行过滤
|
||||
|
||||
* Composing multiple streams
|
||||
|
||||
组合多个流
|
||||
|
||||
## Observable creation functions
|
||||
|
||||
## 创建可观察对象的函数
|
||||
|
||||
RxJS offers a number of functions that can be used to create new observables. These functions can simplify the process of creating observables from things such as events, timers, promises, and so on. For example:
|
||||
|
||||
RxJS 提供了一些用来创建可观察对象的函数。这些函数可以简化根据某些东西创建可观察对象的过程,比如事件、定时器、承诺等等。比如:
|
||||
|
||||
<code-example path="rx-library/src/simple-creation.ts" region="promise" title="Create an observable from a promise"></code-example>
|
||||
|
||||
<code-example path="rx-library/src/simple-creation.ts" region="interval" title="Create an observable from a counter"></code-example>
|
||||
|
@ -28,42 +48,63 @@ RxJS offers a number of functions that can be used to create new observables. Th
|
|||
|
||||
## Operators
|
||||
|
||||
## 操作符
|
||||
|
||||
Operators are functions that build on the observables foundation to enable sophisticated manipulation of collections. For example, RxJS defines operators such as `map()`, `filter()`, `concat()`, and `flatMap()`.
|
||||
|
||||
操作符是基于可观察对象构建的一些对集合进行复杂操作的函数。RxJS 定义了一些操作符,比如 `map()`、`filter()`、`concat()` 和 `flatMap()`。
|
||||
|
||||
Operators take configuration options, and they return a function that takes a source observable. When executing this returned function, the operator observes the source observable’s emitted values, transforms them, and returns a new observable of those transformed values. Here is a simple example:
|
||||
|
||||
操作符接受一些配置项,然后返回一个以来源可观察对象为参数的函数。当执行这个返回的函数时,这个操作符会观察来源可观察对象中发出的值,转换它们,并返回由转换后的值组成的新的可观察对象。下面是一个简单的例子:
|
||||
|
||||
<code-example path="rx-library/src/operators.ts" title="Map operator"></code-example>
|
||||
|
||||
You can use _pipes_ to link operators together. Pipes let you combine multiple functions into a single function. The `pipe()` function takes as its arguments the functions you want to combine, and returns a new function that, when executed, runs the composed functions in sequence.
|
||||
|
||||
你可以使用*管道*来把这些操作符链接起来。管道让你可以把多个由操作符返回的函数组合成一个。`pipe()` 函数以你要组合的这些函数作为参数,并且返回一个新的函数,当执行这个新函数时,就会顺序执行那些被组合进去的函数。
|
||||
|
||||
A set of operators applied to an observable is a recipe—that is, a set of instructions for producing the values you’re interested in. By itself, the recipe doesn’t do anything. You need to call `subscribe()` to produce a result through the recipe.
|
||||
|
||||
应用于某个可观察对象上的一组操作符就像一个菜谱 —— 也就是说,对你感兴趣的这些值进行处理的一组操作步骤。这个菜谱本身不会做任何事。你需要调用 `subscribe()` 来通过这个菜谱生成一个结果。
|
||||
|
||||
Here’s an example:
|
||||
|
||||
例子如下:
|
||||
|
||||
<code-example path="rx-library/src/operators.1.ts" title="Standalone pipe function"></code-example>
|
||||
|
||||
The `pipe()` function is also a method on the RxJS `Observable`, so you use this shorter form to define the same operation:
|
||||
|
||||
`pipe()` 函数也同时是 RxJS 的 `Observable` 上的一个方法,所以你可以用下列简写形式来达到同样的效果:
|
||||
|
||||
<code-example path="rx-library/src/operators.2.ts" title="Observable.pipe function"></code-example>
|
||||
|
||||
### Common operators
|
||||
|
||||
### 常用操作符
|
||||
|
||||
RxJS provides many operators (over 150 of them), but only a handful are used frequently. Here is a list of common operators; for usage examples, see [RxJS 5 Operators By Example](https://github.com/btroncone/learn-rxjs/blob/master/operators/complete.md) in RxJS documentation.
|
||||
|
||||
RxJS 提供了很多操作符(超过 150 个),不过只有少数是常用的。
|
||||
下面是一个常用操作符的列表,要查看用法范例,参见 RxJS 文档中的 [RxJS 5 操作符范例](https://github.com/btroncone/learn-rxjs/blob/master/operators/complete.md)。
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
Note that, for Angular apps, we prefer combining operators with pipes, rather than chaining. Chaining is used in many RxJS examples.
|
||||
|
||||
注意,对于 Angular 应用来说,我们提倡使用管道来组合操作符,而不是使用链式写法。链式写法仍然在很多 RxJS 中使用着。
|
||||
|
||||
</div>
|
||||
|
||||
| Area | Operators |
|
||||
| 类别 | 操作 |
|
||||
| :------------| :----------|
|
||||
| Creation | `from`, `fromPromise`,`fromEvent`, `of` |
|
||||
| Combination | `combineLatest`, `concat`, `merge`, `startWith` , `withLatestFrom`, `zip` |
|
||||
| Filtering | `debounceTime`, `distinctUntilChanged`, `filter`, `take`, `takeUntil` |
|
||||
| Transformation | `bufferTime`, `concatMap`, `map`, `mergeMap`, `scan`, `switchMap` |
|
||||
| Utility | `tap` |
|
||||
| Multicasting | `share` |
|
||||
| 创建 | `from`, `fromPromise`,`fromEvent`, `of` |
|
||||
| 组合 | `combineLatest`, `concat`, `merge`, `startWith` , `withLatestFrom`, `zip` |
|
||||
| 过滤 | `debounceTime`, `distinctUntilChanged`, `filter`, `take`, `takeUntil` |
|
||||
| 转换 | `bufferTime`, `concatMap`, `map`, `mergeMap`, `scan`, `switchMap` |
|
||||
| 工具 | `tap` |
|
||||
| 多播 | `share` |
|
||||
|
||||
## Error handling
|
||||
|
||||
|
@ -71,34 +112,56 @@ RxJS provides many operators (over 150 of them), but only a handful are used fre
|
|||
|
||||
In addition to the `error()` handler that you provide on subscription, RxJS provides the `catchError` operator that lets you handle known errors in the observable recipe.
|
||||
|
||||
除了可以在订阅时提供 `error()` 处理器外,RxJS 还提供了 `catchError` 操作符,它允许你在管道中处理已知错误。
|
||||
|
||||
For instance, suppose you have an observable that makes an API request and maps to the response from the server. If the server returns an error or the value doesn’t exist, an error is produced. If you catch this error and supply a default value, your stream continues to process values rather than erroring out.
|
||||
|
||||
假设你有一个可观察对象,它发起 API 请求,然后对服务器返回的响应进行映射。如果服务器返回了错误或值不存在,就会生成一个错误。如果你捕获这个错误并提供了一个默认值,流就会继续处理这些值,而不会报错。
|
||||
|
||||
Here's an example of using the `catchError` operator to do this:
|
||||
|
||||
下面是使用 `catchError` 操作符实现这种效果的例子:
|
||||
|
||||
<code-example path="rx-library/src/error-handling.ts" title="catchError operator"></code-example>
|
||||
|
||||
### Retry failed observable
|
||||
|
||||
### 重试失败的可观察对象
|
||||
|
||||
Where the `catchError` operator provides a simple path of recovery, the `retry` operator lets you retry a failed request.
|
||||
|
||||
`catchError` 提供了一种简单的方式进行恢复,而 `retry` 操作符让你可以尝试失败的请求。
|
||||
|
||||
Use the `retry` operator before the `catchError` operator. It resubscribes to the original source observable, which can then re-run the full sequence of actions that resulted in the error. If this includes an HTTP request, it will retry that HTTP request.
|
||||
|
||||
可以在 `catchError` 之前使用 `retry` 操作符。它会订阅到原始的来源可观察对象,它可以重新运行导致结果出错的动作序列。如果其中包含 HTTP 请求,它就会重新发起那个 HTTP 请求。
|
||||
|
||||
The following converts the previous example to retry the request before catching the error:
|
||||
|
||||
下列代码为前面的例子加上了捕获错误前重发请求的逻辑:
|
||||
|
||||
<code-example path="rx-library/src/retry-on-error.ts" title="retry operator"></code-example>
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
Do not retry **authentication** requests, since these should only be initiated by user action. We don't want to lock out user accounts with repeated login requests that the user has not initiated.
|
||||
|
||||
不要重试**登录认证**请求,这些请求只应该由用户操作触发。我们肯定不会希望自动重复发送登录请求导致用户的账号被锁定。
|
||||
|
||||
</div>
|
||||
|
||||
## Naming conventions for observables
|
||||
|
||||
## 可观察对象的命名约定
|
||||
|
||||
Because Angular applications are mostly written in TypeScript, you will typically know when a variable is an observable. Although the Angular framework does not enforce a naming convention for observables, you will often see observables named with a trailing “$” sign.
|
||||
|
||||
由于 Angular 的应用几乎都是用 TypeScript 写的,你通常会希望知道某个变量是否可观察对象。虽然 Angular 框架并没有针对可观察对象的强制性命名约定,不过你经常会看到可观察对象的名字以“$”符号结尾。
|
||||
|
||||
This can be useful when scanning through code and looking for observable values. Also, if you want a property to store the most recent value from an observable, it can be convenient to simply use the same name with or without the “$”.
|
||||
|
||||
这在快速浏览代码并查找可观察对象值时会非常有用。同样的,如果你希望用某个属性来存储来自可观察对象的最近一个值,它的命名惯例是与可观察对象同名,但不带“$”后缀。
|
||||
|
||||
For example:
|
||||
|
||||
比如:
|
||||
|
|
|
@ -191,32 +191,32 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"title": "Observables & RxJS",
|
||||
"tooltip": "Observables & RxJS",
|
||||
"title": "Observable 与 RxJS",
|
||||
"tooltip": "Observable 与 RxJS",
|
||||
"children": [
|
||||
{
|
||||
"url": "guide/observables",
|
||||
"title": "Observables",
|
||||
"title": "可观察对象(Observable)",
|
||||
"tooltip": ""
|
||||
},
|
||||
{
|
||||
"url": "guide/rx-library",
|
||||
"title": "The RxJS Library",
|
||||
"title": "RxJS 库",
|
||||
"tooltip": ""
|
||||
},
|
||||
{
|
||||
"url": "guide/observables-in-angular",
|
||||
"title": "Observables in Angular",
|
||||
"title": "Angular 中的可观察对象",
|
||||
"tooltip": ""
|
||||
},
|
||||
{
|
||||
"url": "guide/practical-observable-usage",
|
||||
"title": "Practical Usage",
|
||||
"title": "用法实战",
|
||||
"tooltip": ""
|
||||
},
|
||||
{
|
||||
"url": "guide/comparing-observables",
|
||||
"title": "Compare to Other Techniques",
|
||||
"title": "与其它技术的比较",
|
||||
"tooltip": ""
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue