web-dev-qa-db-fra.com

Redux Saga async/wait pattern

J'utilise async/wait tout au long de ma base de code. A cause de cela, mes appels api sont définis par des fonctions asynchrones.

async function apiFetchFoo {
  return await apiCall(...);
}

Je voudrais appeler cette fonction de mon code de saga. Il semble que je ne peux pas faire ça:

// Doesn't work
function* fetchFoo(action) {
  const results = await apiFetchFoo();
  yield put({type: "FOOS_FETCHED_SUCCESSFULLY", foos: results});
}

Cependant, cela fonctionne et correspond à la documentation de la saga redux:

// Does work
function* fetchFoo(action) {
  const results = yield call(apiFetchFoo);
  yield put({type: "FOOS_FETCHED_SUCCESSFULLY", foos: results});
}

Est-ce la bonne façon d'utiliser Redux Saga aux côtés de async/wait? Il est standard d’utiliser cette syntaxe de générateur dans le code de la saga, et le modèle async/wait ailleurs?

28
mattnedrich

Oui, c'est la manière standard d'utiliser Redux-Saga.

Vous ne devriez jamais appeler la fonction await directement à l'intérieur du générateur de saga, car redux-saga est destiné à orchestrant les effets secondaires. Par conséquent, chaque fois que vous souhaitez utiliser un effet secondaire, vous devez le faire en utilisant l'effet redux-saga (généralement: call ou fork). Si vous le faites directement sans céder avec un effet redux-saga, alors redux-saga ne pourra pas orchestrer l'effet secondaire.

Si vous y réfléchissez, le générateur redux-saga est complètement testable sans avoir besoin de vous moquer de rien. En outre, il est utile de garder les choses découplées: si votre apiFetchFoo retournait une promesse, la saga fonctionnerait toujours de la même manière.

24
Josep

Comme Josep l'a fait remarquer, await ne peut pas être utilisé à l'intérieur d'un générateur. Au lieu de cela, vous devez utiliser un fonction async. . Notez également qu’il s’agit d’une limitation de la fonction async. Il n'est pas imposé par redux-saga.

Au-delà de cela, je voulais également mentionner que c’est un choix conscient des auteurs de la saga redux-saga qui permet à not de permettre aux développeurs d’exprimer sagas sous forme de fonctions async/await.

Les générateurs sont plus puissants que async/await et permettent des fonctionnalités avancées de redux-saga comme coordination des tâches parallèles .

De plus, exprimer les sagas en tant que générateurs nous aide à définir Effets qui sont des objets simples définissant l'effet secondaire. Les effets le rendent très facile de tester nos sagas .

Donc, bien que votre code de travail soit correct, peut-être que ne pas confondre sagas et la fonction async est une bonne idée.

Il suffit de définir votre apiFetchFoo pour renvoyer une promesse qui résout la réponse à la demande. Et lorsque cela se produira, votre saga reprendra avec la results.

 const apiFetchFoo = () =>
   fetch('foo')
     .then(res => res.json())
1

await travaille toujours dans une fonction déclarée async. #thumbRule

async function fetchList () {
  let resp = await fetchApi([params]);
}
0
Venkat