redux rxjs_可观察的RxJS和Redux入门指南

news/2024/7/7 18:41:20

redux rxjs

Redux-Observable is an RxJS-based middleware for Redux that allows developers to work with async actions. It's an alternative to redux-thunk and redux-saga.

Redux-Observable是Redux的基于RxJS的中间件,允许开发人员使用异步操作。 它是redux-thunk和redux-saga的替代方案。

This article covers the basics of RxJS, how to setup Redux-Observables, and some of its practical use-cases. But before that, we need to understand the Observer Pattern.

本文介绍了RxJS的基础知识,如何设置Redux-Observables及其一些实际用例。 但是在此之前,我们需要了解Observer Pattern

观察者模式 (Observer Pattern)

In Observer pattern, an object called "Observable" or "Subject", maintains a collection of subscribers called "Observers." When the subjects' state changes, it notifies all its Observers.

在观察者模式中,称为“可观察”或“主题”的对象维护着称为“观察者”的订户的集合。 当主题的状态更改时,它会通知其所有观察者。

In JavaScript, the simplest example would be event emitters and event handlers.

在JavaScript中,最简单的示例是事件发射器和事件处理程序。

When you do .addEventListener, you are pushing an observer into the subject's collection of observers. Whenever the event happens, the subject notifies all the observers.

当您执行.addEventListener.addEventListener观察者推入主题的观察者集合中。 每当事件发生时,主题都会通知所有观察者。

RxJS (RxJS)

As per the official website,

根据官方网站,

RxJS is JavaScript implementation of ReactiveX, a library for composing asynchronous and event-based programs by using observable sequences.

RxJS是ReactiveX的 JavaScript实现, ReactiveX是一个库,用于通过使用可观察的序列来组成异步和基于事件的程序。

In simple terms, RxJS is an implementation of the Observer pattern. It also extends the Observer pattern by providing operators that allow us to compose Observables and Subjects in a declarative manner.

简单来说,RxJS是Observer模式的实现。 它还通过提供允许我们以声明方式撰写Observable和Subject的运算符,扩展了Observer模式。

Observers, Observables, Operators, and Subjects are the building blocks of RxJS. So let's look at each one in more detail now.

观察者,可观察者,运算符和主题是RxJS的构建块。 因此,让我们现在更详细地看看每个。

观察者 (Observers)

Observers are objects that can subscribe to Observables and Subjects. After subscribing, they can receive notifications of three types - next, error, and complete.

观察者是可以订阅“观察对象”和“主题”的对象。 订阅后,他们可以接收三种类型的通知-下一步,错误和完成。

Any object with the following structure can be used as an Observer.

具有以下结构的任何对象都可以用作观察者。

interface Observer<T> {closed?: boolean;next: (value: T) => void;error: (err: any) => void;complete: () => void;
}

When the Observable pushes next, error, and complete notifications, the Observer's .next, .error, and .complete methods are invoked.

当Observable推送next,error和complete通知时,将调用Observer的.next.error.complete方法。

可观察的 (Observables)

Observables are objects that can emit data over a period of time. It can be represented using the "marble diagram".

可观察对象是可以在一段时间内发出数据的对象。 可以使用“大理石图”表示。

Where the horizontal line represents the time, the circular nodes represent the data emitted by the Observable, and the vertical line indicates that the Observable has completed successfully.

水平线表示时间,圆形节点表示Observable发出的数据,垂直线表示Observable已成功完成。

Observables may encounter an error. The cross represents the error emitted by the Observable.

观察对象可能会遇到错误。 叉号表示Observable发出的误差。

The "completed" and "error" states are final. That means, Observables cannot emit any data after completing successfully or encountering an error.

“完成”和“错误”状态是最终状态。 这意味着,可观察对象在成功完成或遇到错误后无法发出任何数据。

创建一个可观察的 (Creating an Observable)

Observables are created using the new Observable constructor that takes one argument - the subscribe function. Observables can also be created using some operators, but we will talk about that later when we talk about Operators.

Observable使用new Observable构造函数创建,该构造函数带有一个参数-subscription函数。 还可以使用某些运算符来创建可观察对象,但是稍后将在讨论运算符时再进行讨论。

import { Observable } from 'rxjs';const observable = new Observable(subscriber => {// Subscribe function 
});

订阅可观察的 (Subscribing to an Observable)

Observables can be subscribed using their .subscribe method and passing an Observer.

可以使用它们的.subscribe方法预订观察者,并传递观察者。

observable.subscribe({next: (x) => console.log(x),error: (x) => console.log(x),complete: () => console.log('completed');
});

可观察者的执行 (Execution of an Observable)

The subscribe function that we passed to the new Observable constructor is executed every time the Observable is subscribed.

每次订阅Observable时,都会执行传递给new Observable构造函数的new Observable函数。

The subscribe function takes one argument - the Subscriber. The Subscriber resembles the structure of an Observer, and it has the same 3 methods: .next, .error, and .complete.

subscription函数采用一个参数-Subscriber。 订阅服务器类似于观察者的结构,并且具有相同的3种方法: .next.error.complete

Observables can push data to the Observer using the .next method. If the Observable has completed successfully, it can notify the Observer using the .complete method. If the Observable has encountered an error, it can push the error to the Observer using the .error method.

Observable可以使用.next方法将数据推送到Observer。 如果Observable成功完成,则可以使用.complete方法通知Observer。 如果Observable遇到错误,则可以使用.error方法将错误推送到Observer。

// Create an Observable
const observable = new Observable(subscriber => {subscriber.next('first data');subscriber.next('second data');setTimeout(() => {subscriber.next('after 1 second - last data');subscriber.complete();subscriber.next('data after completion'); // <-- ignored}, 1000);subscriber.next('third data');
});// Subscribe to the Observable
observable.subscribe({next: (x) => console.log(x),error: (x) => console.log(x),complete: () => console.log('completed')
});// Outputs:
//
// first data
// second data
// third data
// after 1 second - last data
// completed

可观察的是单播的 (Observables are Unicast)

Observables are unicast, which means Observables can have at most one subscriber. When an Observer subscribes to an Observable, it gets a copy of the Observable that has its own execution path, making the Observables unicast.

可观测值是单播的 ,这意味着可观测值最多可以有一个订户。 当观察者订阅一个Observable时,它将获得具有自己执行路径的Observable副本,从而使Observables单播。

It is like watching a YouTube video. All viewers watch the same video content but, they can be at watching different segments of the video.

就像观看YouTube视频一样。 所有观看者都观看相同的视频内容,但是他们可以观看视频的不同片段。

Example: let us create an Observable that emits 1 to 10 over 10 seconds. Then, subscribe to the Observable once immediately, and again after 5 seconds.

示例 :让我们创建一个Observable,它在10秒钟内发射1到10。 然后,立即订阅一次Observable,然后在5秒钟后再次订阅。

// Create an Observable that emits data every second for 10 seconds
const observable = new Observable(subscriber => {let count = 1;const interval = setInterval(() => {subscriber.next(count++);if (count > 10) {clearInterval(interval);   }}, 1000);
});// Subscribe to the Observable
observable.subscribe({next: value => {console.log(`Observer 1: ${value}`);}
});// After 5 seconds subscribe again
setTimeout(() => {observable.subscribe({next: value => {console.log(`Observer 2: ${value}`);}});
}, 5000);/* OutputObserver 1: 1
Observer 1: 2
Observer 1: 3
Observer 1: 4
Observer 1: 5
Observer 2: 1
Observer 1: 6
Observer 2: 2
Observer 1: 7
Observer 2: 3
Observer 1: 8
Observer 2: 4
Observer 1: 9
Observer 2: 5
Observer 1: 10
Observer 2: 6
Observer 2: 7
Observer 2: 8
Observer 2: 9
Observer 2: 10*/

In the output, you can notice that the second Observer started printing from 1 even though it subscribed after 5 seconds. This happens because the second Observer received a copy of the Observable whose subscribe function was invoked again. This illustrates the unicast behaviour of Observables.

在输出中,您可以注意到第二个观察者从5开始打印,即使它在5秒后订阅了。 发生这种情况是因为第二个Observer收到了Observable的副本,该副本的订阅函数再次被调用。 这说明了可观察对象的单播行为。

科目 (Subjects)

A Subject is a special type of Observable.

主题是可观察的一种特殊类型。

创建一个主题 (Creating a Subject)

A Subject is created using the new Subject constructor.

使用new Subject构造函数创建new Subject

import { Subject } from 'rxjs';// Create a subject
const subject = new Subject();

订阅主题 (Subscribing to a Subject)

Subscribing to a Subject is similar to subscribing to an Observable: you use the .subscribe method and pass an Observer.

订阅主题类似于订阅Observable:使用.subscribe方法并传递一个Observer。

subject.subscribe({next: (x) => console.log(x),error: (x) => console.log(x),complete: () => console.log("done")
});

主题的执行 (Execution of a Subject)

Unlike Observables, a Subject calls its own .next, .error, and .complete methods to push data to Observers.

与Observables不同,Subject调用自己的.next.error.complete方法将数据推送到Observers。

// Push data to all observers
subject.next('first data');// Push error to all observers
subject.error('oops something went wrong');// Complete
subject.complete('done');

主题是多播的 (Subjects are Multicast)

Subjects are multicast: multiple Observers share the same Subject and its execution path. It means all notifications are broadcasted to all the Observers. It is like watching a live program. All viewers are watching the same segment of the same content at the same time.

主题是多播的:多个观察者共享相同的主题及其执行路径。 这意味着所有通知都会广播到所有观察者。 就像观看直播节目一样。 所有观众都在同一时间观看同一内容的同一片段。

Example: let us create a Subject that emits 1 to 10 over 10 seconds. Then, subscribe to the Observable once immediately, and again after 5 seconds.

示例:让我们创建一个在10秒钟内发射1到10的主题。 然后,立即订阅一次Observable,然后在5秒钟后再次订阅。

// Create a subject
const subject = new Subject();let count = 1;
const interval = setInterval(() => {subscriber.next(count++);if (count > 10) {clearInterval(interval);}
}, 1000);// Subscribe to the subjects
subject.subscribe(data => {console.log(`Observer 1: ${data}`);
});// After 5 seconds subscribe again
setTimeout(() => {subject.subscribe(data => {console.log(`Observer 2: ${data}`);});
}, 5000);/* OUTPUTObserver 1: 1
Observer 1: 2
Observer 1: 3
Observer 1: 4
Observer 1: 5
Observer 2: 5
Observer 1: 6
Observer 2: 6
Observer 1: 7
Observer 2: 7
Observer 1: 8
Observer 2: 8
Observer 1: 9
Observer 2: 9
Observer 1: 10
Observer 2: 10*/

In the output, you can notice that the second Observer started printing from 5 instead of starting from 1. This happens because the second Observer is sharing the same Subject. Since it subscribed after 5 seconds, the Subject has already finished emitting 1 to 4. This illustrates the multicast behavior of a Subject.

在输出中,您会注意到第二个Observer从5开始打印,而不是从1开始。这是因为第二个Observer共享相同的Subject。 由于它在5秒钟后订阅,因此主体已经完成发射1到4。这说明了主体的多播行为。

主题既可观察又可观察 (Subjects are both Observable and Observer)

Subjects have the .next, .error and .complete methods. That means that they follow the structure of Observers. Hence, a Subject can also be used as an Observer and passed to the .subscribe function of Observables or other Subjects.

主题具有.next.error.complete方法。 这意味着它们遵循观察者的结构。 因此,主题也可以用作观察者,并传递给Observables或其他主题的.subscribe函数。

Example: let us create an Observable and a Subject. Then subscribe to the Observable using the Subject as an Observer. Finally, subscribe to the Subject. All the values emitted by the Observable will be pushed to the Subject, and the Subject will broadcast the received values to all its Observers.

示例:让我们创建一个Observable和Subject。 然后使用主题作为观察者订阅可观察对象。 最后,订阅主题。 Observable发出的所有值将被推送到Subject,并且Subject将把接收到的值广播到其所有Observer。

// Create an Observable that emits data every second
const observable = new Observable(subscriber => {let count = 1;const interval = setInterval(() => {subscriber.next(count++);if (count > 5) {clearInterval(interval);   }}, 1000);
});// Create a subject
const subject = new Subject();// Use the Subject as Observer and subscribe to the Observable
observable.subscribe(subject);// Subscribe to the subject
subject.subscribe({next: value => console.log(value)
});/* Output1
2
3
4
5*/

经营者 (Operators)

Operators are what make RxJS useful. Operators are pure functions that return a new Observable. They can be categorized into 2 main categories:

运算符使RxJS有用。 运算符是返回新的Observable的纯函数。 它们可以分为2个主要类别:

  1. Creation Operators

    创建运算符
  2. Pipeable Operators

    管道运算符

创建运算符 (Creation Operators)

Creation Operators are functions that can create a new Observable.

创建运算符是可以创建新的Observable的函数。

Example: we can create an Observable that emits each element of an array using the from operator.

示例:我们可以创建一个Observable,它使用from运算符发出数组的每个元素。

const observable = from([2, 30, 5, 22, 60, 1]);observable.subscribe({next: (value) => console.log("Received", value),error: (err) => console.log(err),complete: () => console.log("done")
});/* OUTPUTSReceived 2
Received 30
Received 5
Received 22
Received 60
Received 1
done*/

The same can be an Observable using the marble diagram.

使用大理石图可以观察到的结果相同。

管道运算符 (Pipeable Operators)

Pipeable Operators are functions that take an Observable as an input and return a new Observable with modified behavior.

管道运算符是将Observable用作输入并返回具有已修改行为的新Observable的函数。

Example: let's take the Observable that we created using the from operator. Now using this Observable, we can to create a new Observable that emits only numbers greater than 10 using the filter operator.

示例:让我们使用使用from运算符创建的Observable。 现在使用此Observable,我们可以使用filter运算符创建一个仅发出大于10的数字的新Observable。

const greaterThanTen = observable.pipe(filter(x => x > 10));greaterThanTen.subscribe(console.log, console.log, () => console.log("completed"));// OUTPUT
// 11
// 12
// 13
// 14
// 15

The same can be represented using the marble diagram.

可以使用大理石图表示相同的内容。

There are many more useful operators out there. You can see the full operators list along with examples on the official RxJS documentation here.

还有更多有用的运算符。 您可以在此处查看完整的运算符列表以及RxJS官方文档中的示例。

It is crucial to understand all the commonly used operators. Here are some operators that I use often:

了解所有常用的运算符至关重要。 这是我经常使用的一些运算符:

  1. mergeMap

    mergeMap

  2. switchMap

    switchMap

  3. exhaustMap

    exhaustMap

  4. map

    map

  5. catchError

    catchError

  6. startWith

    startWith

  7. delay

    delay

  8. debounce

    debounce

  9. throttle

    throttle

  10. interval

    interval

  11. from

    from

  12. of

    of

Redux可观察物 (Redux Observables)

As per the official website,

根据官方网站,

RxJS-based middleware for Redux. Compose and cancel async actions to create side effects and more.

基于RxJS的Redux中间件。 撰写和取消异步操作以创建副作用等。

In Redux, whenever an action is dispatched, it runs through all the reducer functions and a new state is returned.

在Redux中,每当分派动作时,它就会通过所有reducer函数运行并返回新状态。

Redux-observable takes all these dispatched actions and new states and creates two observables out of it - Actions observable action$, and States observable state$.

Redux-observable采取所有这些调度的动作和新状态,并在其中创建两个可观察对象-Actions observable action$和States observable state$

Actions observable will emit all the actions that are dispatched using the store.dispatch(). States observable will emit all the new state objects returned by the root reducer.

可观察到的动作将发出使用store.dispatch()调度的所有动作。 可观察到的状态将发出由根减速器返回的所有新状态对象。

史诗 (Epics)

As per the official website,

根据官方网站,

It is a function which takes a stream of actions and returns a stream of actions. Actions in, actions out.

该函数需要一系列操作并返回一系列操作。 行动,行动。

Epics are functions that can be used to subscribe to Actions and States Observables. Once subscribed, epics will receive the stream of actions and states as input, and it must return a stream of actions as an output. Actions In - Actions Out.

史诗是可用于订阅“动作”和“可观察状态”的功能。 订阅后,史诗将接收动作和状态流作为输入,并且它必须返回动作流作为输出。 行动在行动在行动

const someEpic = (action$, state$) => { return action$.pipe( // subscribe to actions observablemap(action => { // Receive every action, Actions Inreturn someOtherAction(); // return an action, Actions Out}))
}

It is important to understand that all the actions received in the Epic have already finished running through the reducers.

重要的是要了解Epic中收到的所有动作都已经通过减速器完成了

Inside an Epic, we can use any RxJS observable patterns, and this is what makes redux-observables useful.

在Epic内部,我们可以使用任何RxJS可观察模式,这就是使redux-observable有用的原因。

Example: we can use the .filter operator to create a new intermediate observable. Similarly, we can create any number of intermediate observables, but the final output of the final observable must be an action, otherwise an exception will be raised by redux-observable.

示例:我们可以使用.filter运算符创建一个新的中间可观察对象。 同样,我们可以创建任意数量的中间可观察变量,但是最终可观察变量的最终输出必须是一个动作,否则redux-observable会引发异常。

const sampleEpic = (action$, state$) => {return action$.pipe(filter(action => action.payload.age >= 18), // can create intermediate observables and streamsmap(value => above18(value)) // where above18 is an action creator);
}

Every action emitted by the Epics are immediately dispatched using the store.dispatch().

Epics发出的每个动作都会立即使用store.dispatch()调度。

建立 (Setup)

First, let's install the dependencies.

首先,让我们安装依赖项。

npm install --save rxjs redux-observable

Create a separate folder named epics to keep all the epics. Create a new file index.js inside the epics folder and combine all the epics using the combineEpics function to create the root epic. Then export the root epic.

创建一个名为epics的单独文件夹以保留所有史诗。 创建一个新的文件index.js里面的epics文件夹,然后将所有使用的史诗combineEpics函数来创建根史诗。 然后导出根史诗。

import { combineEpics } from 'redux-observable';
import { epic1 } from './epic1';
import { epic2 } from './epic2';const epic1 = (action$, state$) => {...   
}const epic2 = (action$, state$) => {...   
}export default combineEpics(epic1, epic2);

Create an epic middleware using the createEpicMiddleware function and pass it to the createStore Redux function.

使用createEpicMiddleware函数创建一个史诗中间件,并将其传递给createStore Redux函数。

import { createEpicMiddleware } from 'redux-observable';
import { createStore, applyMiddleware } from 'redux';
import rootEpic from './rootEpics';const epicMiddleware = createEpicMiddlware();const store = createStore(rootReducer,applyMiddleware(epicMiddlware)
);

Finally, pass the root epic to epic middleware's .run method.

最后,将根史诗传递给史诗中间件的.run方法。

epicMiddleware.run(rootEpic);

一些实际用例 (Some Practical Usecases)

RxJS has a big learning curve, and the redux-observable setup worsens the already painful Redux setup process. All that makes Redux observable look like an overkill. But here are some practical use cases that can change your mind.

RxJS的学习曲线很大,可观察到的Redux设置会使本来就很痛苦的Redux设置过程恶化。 所有使Redux都可观察到的东西看起来像是一个过大的杀伤力。 但是这里有一些可以改变主意的实际用例。

Throughout this section, I will be comparing redux-observables with redux-thunk to show how redux-observables can be helpful in complex use-cases. I don't hate redux-thunk, I love it, and I use it every day!

在本节中,我将比较redux-observables和redux-thunk,以显示redux-observables如何在复杂的用例中提供帮助。 我不讨厌redux-thunk,我喜欢它,并且每天都在使用它!

1.进行API调用 (1. Make API Calls)

Usecase: Make an API call to fetch comments of a post. Show loaders when the API call is in progress and also handle API errors.

用例:进行API调用以获取帖子的评论。 在API调用正在进行时显示加载程序,并处理API错误。

A redux-thunk implementation will look like this,

一个redux-thunk实现将如下所示,

function getComments(postId){return (dispatch) => {dispatch(getCommentsInProgress());axios.get(`/v1/api/posts/${postId}/comments`).then(response => {dispatch(getCommentsSuccess(response.data.comments));}).catch(() => {dispatch(getCommentsFailed());});}
}

and this is absolutely correct. But the action creator is bloated.

这是绝对正确的。 但是动作创造者is肿。

We can write an Epic to implement the same using redux-observables.

我们可以编写一个Epic以使用redux-observables实现相同的功能。

const getCommentsEpic = (action$, state$) => action$.pipe(ofType('GET_COMMENTS'),mergeMap((action) => from(axios.get(`/v1/api/posts/${action.payload.postId}/comments`).pipe(map(response => getCommentsSuccess(response.data.comments)),catchError(() => getCommentsFailed()),startWith(getCommentsInProgress()))
);

Now it allows us to have a clean and simple action creator like this,

现在,它使我们可以像这样一个干净整洁的动作创建者,

function getComments(postId) {return {type: 'GET_COMMENTS',payload: {postId}}
}

2.请求退信 (2. Request Debouncing)

Usecase: Provide autocompletion for a text field by calling an API whenever the value of the text field changes. API call should be made 1 second after the user has stopped typing.

用例:每当文本字段的值更改时,通过调用API来为文本字段提供自动补全功能。 用户停止输入后应在1秒钟内进行API调用。

A redux-thunk implementation will look like this,

一个redux-thunk实现将如下所示,

let timeout;function valueChanged(value) {return dispatch => {dispatch(loadSuggestionsInProgress());dispatch({type: 'VALUE_CHANGED',payload: {value}});// If changed again within 1 second, cancel the timeouttimeout && clearTimeout(timeout);// Make API Call after 1 secondtimeout = setTimeout(() => {axios.get(`/suggestions?q=${value}`).then(response =>dispatch(loadSuggestionsSuccess(response.data.suggestions))).catch(() => dispatch(loadSuggestionsFailed()))}, 1000, value);}
}

It requires a global variable timeout. When we start using global variables, our action creators are not longer pure functions. It also becomes difficult to unit test the action creators that use a global variable.

它需要全局变量timeout 。 当我们开始使用全局变量时,动作创建者不再是纯函数。 对使用全局变量的动作创建者进行单元测试也变得困难。

We can implement the same with redux-observable using the .debounce operator.

我们可以使用.debounce运算符,通过redux-observable实现相同的.debounce

const loadSuggestionsEpic = (action$, state$) => action$.pipe(ofType('VALUE_CHANGED'),debounce(1000),mergeMap(action => from(axios.get(`/suggestions?q=${action.payload.value}`)).pipe(map(response => loadSuggestionsSuccess(response.data.suggestions)),catchError(() => loadSuggestionsFailed()))),startWith(loadSuggestionsInProgress())
);

Now, our action creators can be cleaned up, and more importantly, they can be pure functions again.

现在,我们的动作创建者可以被清理,更重要的是,他们可以再次成为纯函数。

function valueChanged(value) {return {type: 'VALUE_CHANGED',payload: {value}}
}

3.要求取消 (3. Request Cancellation)

Usecase: Continuing the previous use-case, assume that the user didn't type anything for 1 second, and we made our 1st API call to fetch the suggestions.

用例:继续前面的用例,假设用户在1秒钟内未键入任何内容,并且我们进行了第1次API调用以获取建议。

Let's say the API itself takes an average of 2-3 seconds to return the result. Now, if the user types something while the 1st API call is in progress, after 1 second, we will make our 2nd API. We can end up having two API calls at the same time, and it can create a race condition.

假设API本身平均需要2-3秒才能返回结果。 现在,如果用户在进行第一个API调用时键入了一些内容,则在1秒钟后,我们将创建第二个API。 我们最终可能同时拥有两个API调用,并且它可以创建竞争条件。

To avoid this, we need to cancel the 1st API call before making the 2nd API call.

为避免这种情况,我们需要先取消第一个API调用,然后再进行第二个API调用。

A redux-thunk implementation will look like this,

一个redux-thunk实现将如下所示,

let timeout;
var cancelToken = axios.cancelToken;
let apiCall;function valueChanged(value) {    return dispatch => {dispatch(loadSuggestionsInProgress());dispatch({type: 'VALUE_CHANGED',payload: {value}});// If changed again within 1 second, cancel the timeouttimeout && clearTimeout(timeout);// Make API Call after 1 secondtimeout = setTimeout(() => {// Cancel the existing APIapiCall && apiCall.cancel('Operation cancelled');// Generate a new tokenapiCall = cancelToken.source();axios.get(`/suggestions?q=${value}`, {cancelToken: apiCall.token}).then(response => dispatch(loadSuggestionsSuccess(response.data.suggestions))).catch(() => dispatch(loadSuggestionsFailed()))}, 1000, value);}
}

Now, it requires another global variable to store the Axios's cancel token. More global variables = more impure functions!

现在,它需要另一个全局变量来存储Axios的cancel令牌。 更多全局变量=更多不纯函数!

To implement the same using redux-observable, all we need to do is replace .mergeMap with .switchMap.

为了使用redux-observable实现相同的功能,我们要做的就是将.mergeMap替换为.switchMap

const loadSuggestionsEpic = (action$, state$) => action$.pipe(ofType('VALUE_CHANGED'),throttle(1000),switchMap(action => from(axios.get(`/suggestions?q=${action.payload.value}`)).pipe(map(response => loadSuggestionsSuccess(response.data.suggestions)),catchError(() => loadSuggestionsFailed()))),startWith(loadSuggestionsInProgress())
);

Since it doesn't require any changes to our action creators, they can continue to be pure functions.

由于不需要对我们的动作创建者进行任何更改,因此他们可以继续成为纯函数。

Similarly, there are many use-cases where Redux-Observables actually shines! For example, polling an API, showing snack bars, managing WebSocket connections, etc.

同样,在很多用例中,Redux-Observables确实发光! 例如,轮询API,显示小吃店, 管理WebSocket连接等。

结论 (To Conclude)

If you are developing a Redux application that involves such complex use-cases, it is highly recommended to use Redux-Observables. After all, the benefits of using it are directly proportional to the complexity of your application, and it is evident from the above mentioned practical use-cases.

如果您正在开发涉及此类复杂用例的Redux应用程序,则强烈建议使用Redux-Observables。 毕竟,使用它的好处与您的应用程序的复杂度成正比,并且从上述实际用例中可以明显看出。

I strongly believe using the right set of libraries will help us to develop much cleaner and maintainable applications, and in the long term, the benefits of using them will outweigh the drawbacks.

我坚信使用正确的库集将帮助我们开发更清洁和可维护的应用程序 ,从长远来看,使用它们的好处将超过弊端。

翻译自: https://www.freecodecamp.org/news/beginners-guide-to-rxjs-redux-observables/

redux rxjs


http://lihuaxi.xjx100.cn/news/237309.html

相关文章

以太坊系统账户

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 在以太坊系统中&#xff0c;状态是由被称为“账户”&#xff08;每个账户由一个20字节的地址&#xff09;的对象和在两个账户之间转移价值和信息的状…

c# 持续集成 单元测试_如何在不进行单元测试的情况下设置持续集成

c# 持续集成 单元测试Do you think continuous integration is not for you because you have no automated tests? Or no unit tests at all? Not true. Tests are important. But there are many more aspects to continuous integration than just testing. Lets see what…

[20180317]12c TABLE ACCESS BY INDEX ROWID BATCHED2.txt

[20180317]12c TABLE ACCESS BY INDEX ROWID BATCHED2.txt--//简单探究12c TABLE ACCESS BY INDEX ROWID BATCHED特性.--//当使用12c时,执行计划出现TABLE ACCESS BY INDEX ROWID BATCHED,做一些探究.--//本文主要探究如何使用提示或者隐含参数控制这种特性.1.环境:SCOTTtest01…

解析equals(Object obj)和compareTo(T obj)

背景&#xff1a;最近在研究静态扫描的东西&#xff0c;遇到一个规则&#xff1a;"equals(Object obj)" should be overridden along with the "compareTo(T obj)" method 然后就想深度扒一扒equals和compareTo有什么区别 1.java.lang.Object是所有类的父类…

区块链技术名词简介

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 零知识证明 零知识证明指证明者能在不向验证者提供任何有用的信息下&#xff0c;使验证者相信某个论断是正确的。零知识证明实质是一种涉及两方或更…

RPC-原理及RPC实例分析

还有就是&#xff1a;RPC支持的BIO,NIO的理解 (1)BIO: Blocking IO;同步阻塞&#xff1b; (2)NIO:Non-Blocking IO&#xff0c; 同步非阻塞; 参考&#xff1a;IO多路复用,同步&#xff0c;异步&#xff0c;阻塞和非阻塞 区别 在学校期间大家都写过不少程序&#xff0c;比如写个…

C++基础技术简介

链客&#xff0c;专为开发者而生&#xff0c;有问必答&#xff01; 此文章来自区块链技术社区&#xff0c;未经允许拒绝转载。 容器 容器用于存储数据元素&#xff0c;是由长度可变的同类型的元素构建成的序列。 Vector&#xff1a;用于快速定位任意元素及主要在元素序列的尾…

客户旅程_编程如何找到我的:21岁开发人员的7年旅程

客户旅程Ive read some amazing stories about peoples coding journeys here, and I was interested to share my own as well. Before starting out with anything about my journey, let me introduce myself quickly here, and then well go into flashback mode. 我在这里…