Heim  >  Artikel  >  Web-Frontend  >  Was ist Reaktions-Middleware?

Was ist Reaktions-Middleware?

青灯夜游
青灯夜游Original
2020-11-26 17:16:015276Durchsuche

Middleware ist eine Funktion, die zwischen den beiden Schritten „Action“ und „Reducer“ hinzugefügt wurde das Modul.

Was ist Reaktions-Middleware?

1. Das Konzept der Middleware

Um Middleware zu verstehen, betrachten wir das Problem aus der Perspektive des Framework-Autors: Wenn Sie Funktionen hinzufügen möchten, wo werden Sie diese hinzufügen?

(1) Reduzierer: Reine Funktion, die nur die Funktion der Zustandsberechnung ausführt. Sie ist nicht für andere Funktionen geeignet und kann nicht ausgeführt werden, da reine Funktionen theoretisch keine Lese- und Schreibvorgänge ausführen können.

(2) Ansicht: Entspricht eins zu eins dem Zustand, kann als visuelle Schicht des Staates angesehen werden und ist nicht für andere Funktionen geeignet.

(3) Aktion: Das Objekt, das Daten speichert, also der Träger der Nachricht, kann nur von anderen bedient werden und kann selbst keine Operationen ausführen.

Nach langem Überlegen kann nur der Schritt des Sendens einer Aktion, also die Methode store.dispatch(), Funktionalität hinzufügen. Um beispielsweise eine Protokollierungsfunktion hinzuzufügen und Aktion und Status auszudrucken, können Sie „store.dispatch“ wie folgt ändern.

let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
  console.log('dispatching', action);
  next(action);
  console.log('next state', store.getState());
}

Im obigen Code wird store.dispatch neu definiert und die Druckfunktion wird vor und nach dem Senden der Aktion hinzugefügt. Dies ist der Prototyp der Middleware.

Middleware ist eine Funktion, die die Methode store.dispatch ändert und zwischen den beiden Schritten der Ausgabe einer Aktion und der Ausführung von Reducer weitere Funktionen hinzufügt. Häufig verwendete Middleware ist fertig. Schauen Sie sich einfach die von anderen geschriebenen Module an.

2. Verwendung von Middleware

In diesem Tutorial geht es nicht um das Schreiben von Middleware, da häufig verwendete Middleware fertig ist und Sie nur auf von anderen geschriebene Module verweisen müssen. Beispielsweise verfügt die Protokoll-Middleware im vorherigen Abschnitt über ein vorgefertigtes Redux-Logger-Modul. Hier stellen wir nur die Verwendung von Middleware vor.

import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
 
const store = createStore(
  reducer,
  applyMiddleware(logger)
);

Im obigen Code stellt redux-logger einen Generator createLogger bereit, der einen Log-Middleware-Logger generieren kann. Fügen Sie es dann in die Methode applyMiddleware ein und übergeben Sie es an die Methode createStore, um die Funktionserweiterung von store.dispatch() abzuschließen.

Hier sind zwei Punkte zu beachten:

(1) Die Methode createStore kann den Anfangszustand der gesamten Anwendung als Parameter akzeptieren. In diesem Fall ist applyMiddleware der dritte Parameter.

const store = createStore(
  reducer,
  initial_state,
  applyMiddleware(logger)
);

(2) Die Reihenfolge der Middleware ist wichtig.

const store = createStore(
  reducer,
  applyMiddleware(thunk, promise, logger)
);

Im obigen Code sind die drei Parameter der applyMiddleware-Methode drei Middlewares. Für einige Middleware gelten Bestellanforderungen. Überprüfen Sie daher die Dokumentation, bevor Sie sie verwenden. Beispielsweise muss der Logger am Ende platziert werden, da sonst die Ausgabeergebnisse falsch sind.

3. applyMiddlewares()

Wenn Sie das sehen, fragen Sie sich vielleicht: Was genau macht die applyMiddlewares-Methode?

Es handelt sich um eine native Methode von Redux. Ihre Funktion besteht darin, ein Array aller Middleware zu bilden und diese nacheinander auszuführen. Unten finden Sie den Quellcode.

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer);
    var dispatch = store.dispatch;
    var chain = [];
 
    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = compose(...chain)(store.dispatch);
 
    return {...store, dispatch}
  }
}

Im obigen Code wird die gesamte Middleware in eine Array-Kette gestellt, dann zur Ausführung verschachtelt und schließlich wird store.dispatch ausgeführt. Wie Sie sehen, stehen in der Middleware (MiddlewareAPI) die beiden Methoden getState und Dispatch zur Verfügung.

4. Die Grundidee asynchroner Vorgänge

Nachdem Sie die Middleware verstanden haben, können Sie mit asynchronen Vorgängen umgehen.

Synchronische Vorgänge müssen nur eine Aktion ausführen. Der Unterschied zwischen asynchronen Vorgängen besteht darin, dass sie drei Aktionen ausführen müssen.

  • Aktion, wenn der Vorgang initiiert wird.

  • Aktion, wenn der Vorgang erfolgreich ist verschiedene Wege.

    // 写法一:名称相同,参数不同
    { type: 'FETCH_POSTS' }
    { type: 'FETCH_POSTS', status: 'error', error: 'Oops' }
    { type: 'FETCH_POSTS', status: 'success', response: { ... } }
    // 写法二:名称不同
    { type: 'FETCH_POSTS_REQUEST' }
    { type: 'FETCH_POSTS_FAILURE', error: 'Oops' }
    { type: 'FETCH_POSTS_SUCCESS', response: { ... } }
  • Zusätzlich zu den verschiedenen Aktionstypen muss auch der Status asynchroner Vorgänge geändert werden, um unterschiedliche Betriebszustände widerzuspiegeln. Unten finden Sie ein Beispiel für „State“.
  • let state = {
      // ... 
      isFetching: true,
      didInvalidate: true,
      lastUpdated: 'xxxxxxx'
    };

    Im obigen Code gibt das Attribut isFetching of State an, ob Daten abgerufen werden. didInvalidate gibt an, ob die Daten veraltet sind, und lastUpdated gibt den Zeitpunkt der letzten Aktualisierung an.

  • Jetzt ist die Idee des gesamten asynchronen Betriebs sehr klar.

Wenn der Vorgang beginnt, senden Sie eine Aktion, der Auslöserstatus wird auf den Status „Vorgang läuft“ aktualisiert und die Ansicht wird neu gerendert.

Nachdem der Vorgang abgeschlossen ist, wird eine weitere Aktion gesendet. Der Triggerstatus wird auf den Status „Operation beendet“ aktualisiert und die Ansicht wird erneut gerendert. 5. Redux-Thunk-Middleware. Asynchrone Operationen müssen mindestens zwei Aktionen senden: die Der Benutzer löst die erste Aktion aus, die mit der synchronen Operation identisch ist. Wie können wir dies am Ende der Operation tun? Was ist mit dem automatischen Senden der zweiten Aktion?

    Das Geheimnis liegt im Action Creator.
  • class AsyncApp extends Component {
      componentDidMount() {
        const { dispatch, selectedPost } = this.props
        dispatch(fetchPosts(selectedPost))
      }
    // ...

    Der obige Code ist ein Beispiel für eine asynchrone Komponente. Nach erfolgreichem Laden (componentDidMount-Methode) sendet es (Dispatch-Methode) eine Aktion, um Daten fetchPosts(selectedSubreddit) vom Server anzufordern. Die fetchPosts hier sind Action Creator.

  • Das Folgende ist der Code von fetchPosts, der entscheidende Punkt ist darin.
  • const fetchPosts = postTitle => (dispatch, getState) => {
      dispatch(requestPosts(postTitle));
      return fetch(`/some/API/${postTitle}.json`)
        .then(response => response.json())
        .then(json => dispatch(receivePosts(postTitle, json)));
      };
    };
    // 使用方法一
    store.dispatch(fetchPosts('reactjs'));
    // 使用方法二
    store.dispatch(fetchPosts('reactjs')).then(() =>
      console.log(store.getState())
    );

    上面代码中,fetchPosts是一个Action Creator(动作生成器),返回一个函数。这个函数执行后,先发出一个Action(requestPosts(postTitle)),然后进行异步操作。拿到结果后,先将结果转成 JSON 格式,然后再发出一个 Action( receivePosts(postTitle, json))。

    上面代码中,有几个地方需要注意。

    (1)fetchPosts返回了一个函数,而普通的 Action Creator 默认返回一个对象。

    (2)返回的函数的参数是dispatch和getState这两个 Redux 方法,普通的 Action Creator 的参数是 Action 的内容。

    (3)在返回的函数之中,先发出一个 Action(requestPosts(postTitle)),表示操作开始。

    (4)异步操作结束之后,再发出一个 Action(receivePosts(postTitle, json)),表示操作结束。

    这样的处理,就解决了自动发送第二个 Action 的问题。但是,又带来了一个新的问题,Action 是由store.dispatch方法发送的。而store.dispatch方法正常情况下,参数只能是对象,不能是函数。

    这时,就要使用中间件redux-thunk。

    import { createStore, applyMiddleware } from 'redux';
    import thunk from 'redux-thunk';
    import reducer from './reducers';
    // Note: this API requires redux@>=3.1.0
    const store = createStore(
      reducer,
      applyMiddleware(thunk)
    );

    上面代码使用redux-thunk中间件,改造store.dispatch,使得后者可以接受函数作为参数。

    因此,异步操作的第一种解决方案就是,写出一个返回函数的 Action Creator,然后使用redux-thunk中间件改造store.dispatch。

    六、redux-promise 中间件

    既然 Action Creator 可以返回函数,当然也可以返回其他值。另一种异步操作的解决方案,就是让 Action Creator 返回一个 Promise 对象。

    这就需要使用redux-promise中间件。

    import { createStore, applyMiddleware } from 'redux';
    import promiseMiddleware from 'redux-promise';
    import reducer from './reducers';
     
    const store = createStore(
      reducer,
      applyMiddleware(promiseMiddleware)
    );

    这个中间件使得store.dispatch方法可以接受 Promise 对象作为参数。这时,Action Creator 有两种写法。写法一,返回值是一个 Promise 对象。

    const fetchPosts = 
      (dispatch, postTitle) => new Promise(function (resolve, reject) {
         dispatch(requestPosts(postTitle));
         return fetch(`/some/API/${postTitle}.json`)
           .then(response => {
             type: 'FETCH_POSTS',
             payload: response.json()
           });
    });

    写法二,Action 对象的payload属性是一个 Promise 对象。这需要从redux-actions模块引入createAction方法,并且写法也要变成下面这样。

    import { createAction } from 'redux-actions';
     
    class AsyncApp extends Component {
      componentDidMount() {
        const { dispatch, selectedPost } = this.props
        // 发出同步 Action
        dispatch(requestPosts(selectedPost));
        // 发出异步 Action
        dispatch(createAction(
          'FETCH_POSTS', 
          fetch(`/some/API/${postTitle}.json`)
            .then(response => response.json())
        ));
      }

    上面代码中,第二个dispatch方法发出的是异步 Action,只有等到操作结束,这个 Action 才会实际发出。注意,createAction的第二个参数必须是一个 Promise 对象。

    看一下redux-promise的源码,就会明白它内部是怎么操作的。

    export default function promiseMiddleware({ dispatch }) {
      return next => action => {
        if (!isFSA(action)) {
          return isPromise(action)
            ? action.then(dispatch)
            : next(action);
        }
     
        return isPromise(action.payload)
          ? action.payload.then(
              result => dispatch({ ...action, payload: result }),
              error => {
                dispatch({ ...action, payload: error, error: true });
                return Promise.reject(error);
              }
            )
          : next(action);
      };
    }

    从上面代码可以看出,如果 Action 本身是一个 Promise,它 resolve 以后的值应该是一个 Action 对象,会被dispatch方法送出(action.then(dispatch)),但 reject 以后不会有任何动作;如果 Action 对象的payload属性是一个 Promise 对象,那么无论 resolve 和 reject,dispatch方法都会发出 Action。

Das obige ist der detaillierte Inhalt vonWas ist Reaktions-Middleware?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn