Redux Saga async/await modèle
Je suis en utilisant async/await tout au long de ma base de code. De ce fait mes appels de l'api sont définies par async fonctions
async function apiFetchFoo {
return await apiCall(...);
}
Je voudrais appeler cette fonction à partir de ma saga code. Il me semble que je ne peut pas faire cela:
//Doesn't work
function* fetchFoo(action) {
const results = await apiFetchFoo();
yield put({type: "FOOS_FETCHED_SUCCESSFULLY", foos: results});
}
Toutefois, cela fonctionne, et correspond à la redux saga de la documentation:
//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 les Redux Saga côtés async/await? Il est standard pour utiliser ce générateur de la syntaxe à l'intérieur de la saga de code, et la async/await modèle d'ailleurs?
- Curieux, dans async/await motif pourquoi êtes-vous à l'aide de
function *() { ... await }
au lieu deasync function () { .. await ...}
? Je suis assez sûr que si vous utilisez attendent sans async elle conduit à une erreur "en attente est réservé javascript mot-clé".
Vous devez vous connecter pour publier un commentaire.
Oui, c'est la manière standard d'utilisation Redux-Saga.
Vous ne devriez jamais appeler la
await
fonction directement à l'intérieur de la saga-générateur, parce que redux-saga est pour l'orchestration de les effets secondaires. Par conséquent, chaque fois que vous voulez exécuter un des effets secondaires que vous devriez le faire en produisant les effets secondaires par l'intermédiaire d'unredux-saga
effet (généralement:call
oufork
). Si vous le faites directement, sans céder à travers unredux-saga
effet, alorsredux-saga
ne sera pas en mesure d'orchestrer les effets secondaires.Si vous pensez à ce sujet, le redux-saga générateur est complètement testable sans la nécessité de se moquer de quelque chose. Cela aide aussi à garder les choses découplé: si votre
apiFetchFoo
retourné une promesse, la saga aurait toujours fonctionner de la même.await
une Promesse qui n'a eu aucun des effets secondaires? Il me semble qu'il serait valable de cas d'utilisation de générateurs asynchrones, mais il ne semble pas comme Redux-Saga permet pour eux.call
effet à l'intérieur de la redux-saga générateur qui appelle cette promesse/générateur/whatever.react-saga
documentation de pourquoi il ne faut pas invoquer asynchrone fonctions directement dans la saga: redux-saga.js.org/docs/basics/DeclarativeEffects.html. Conformément à cette documentation, saga devrait produire des effets de la saga de middleware et de la saga de middleware d'exécuter la vigueur et la main sur le résultat de la saga. Les effets sont simples objets JS dire, de middleware, de quoi faire. Toute cette idée de donner des effets à la saga middleware de faire des tests unitaires de la saga simple, sans se moquant async des choses comme les appels d'API.await
toujours travailler au sein d'une fonction qui est déclaré commeasync
. #thumbRuleComme l'a souligné Josep,
await
ne peut pas être utilisé à l'intérieur d'un générateur. Au lieu de cela, vous devez utiliser un fonction async. Aussi, remarque c'est une limitation de l'asynchrone en fonction de lui-même. Il n'est pas imposé par redux-saga.Au-delà de cela, je voulais aussi mentionner que c'est une choix conscient par le redux-saga auteurs de pas permettre devs pour exprimer des sagas comme
async/await
fonctions.Générateurs sont plus puissants que les
async/await
et ils permettent à des fonctionnalités avancées de redux-saga comme co-coordination de tâches en parallèle.En outre, exprimant des sagas comme les générateurs de nous aider à définir Effets qui sont de simples objets de la définition de l'effet indésirable. Effets rend très facile de tester nos sagas.
Ainsi, bien que votre code de travail est bien, peut-être de ne pas mélanger les sagas et de la fonction async est une bonne idée.
Il suffit de définir votre
apiFetchFoo
de retour d'une promesse qui se résout avec la réponse à la demande. Et quand cela arrive, votre saga reprend avec leresults
.