Gathering detailed insights and metrics for create-async-saga
Gathering detailed insights and metrics for create-async-saga
Gathering detailed insights and metrics for create-async-saga
Gathering detailed insights and metrics for create-async-saga
For those that use both redux-toolkit and redux-saga, it is like createAsyncThunk, but using generator instead of asynchronous callback.
npm install create-async-saga
Typescript
Module System
TypeScript (98.59%)
JavaScript (1.41%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
7 Stars
65 Commits
1 Watchers
1 Branches
1 Contributors
Updated on Jun 28, 2025
Latest Version
2.1.13
Package Id
create-async-saga@2.1.13
Unpacked Size
17.34 kB
Size
5.46 kB
File Count
15
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
3
2
For those that use both redux-toolkit and redux-saga, it is like createAsyncThunk, but using generator instead of asynchronous callback.
createAsyncSaga accepts a Redux action type string and generator function. It generates lifecycle action types based on the action type prefix that you pass in, and returns an object that allow to
!! You must have redux-toolkit & redux-saga installed and configured
You want to load a user using an api:
1interface User { 2 userId: number, 3 name: string; 4} 5 6const fetchUserApi = (userId: number): User => ({ userId, name: "foo" });
Call createAsyncSaga and provide a generator that call the API:
1export const fetchUser = createAsyncSaga( 2 'users/fetch', 3 function* (userId: number) { 4 return yield call(fetchUserApi, userId) 5 } 6);
fetchUser object contains action and it's type, the action to execute the saga. It has to be watched and dispatched
1export function* watchFetchUser() { 2 yield takeEvery(fetchUser.actionType, fetchUser.asyncSaga); 3} 4// Don't forget to add this to the saga middleware: sagaMiddleware.run(watchFetchUser)
1dispatch(fetchUser.action(1))
1export function* watchFetchUser() { 2 yield takeEvery(myOwnAction, fetchUser.asyncSaga); 3}
CreateAsyncSaga dispatch a pending action when the saga start, a fulfilled action when the saga is sucessfull, and a rejected action when saga failed. Like with createAsyncThunk, you write your own reducer logic using those actions:
1createSlice({ 2 name: 'user', 3 initialState: { ... }, 4 reducers: { ... }, 5 extraReducers(builder) { 6 builder.addCase( 7 fetchUser.pending, 8 (state) => { 9 state.fetchStatus = "pending"; 10 } 11 ); 12 builder.addCase( 13 fetchUser.fulfilled, 14 (state, action) => { 15 state.fetchStatus = "fulfilled"; 16 state.user = action.payload; 17 } 18 ); 19 builder.addCase( 20 fetchUser.rejected, 21 (state) => { 22 state.fetchStatus = "rejected"; 23 // action.payload contains error information 24 } 25 ); 26 } 27});
Release 2.0.0 includes requestId in actions. This implies a modification in actions creator interface, which is a breaking change. This impact only code that creates action by itself (which is probably test including full saga if any).
1function createAsyncSaga<Returned, Arg>(typePrefix: string, payloadCreator: PayloadCreator<Returned, Arg>, options?: AsyncSagaOptions<Arg>) 2 3type PayloadCreator<Returned, Arg> = (arg: Arg) => Generator<any, Returned, any>; 4 5interface AsyncSagaOptions<Arg> { 6 condition?: Condition<Arg>, 7 dispatchConditionRejection?: boolean, 8} 9 10type Condition<Arg> = (arg: Arg) => Generator<any, boolean, any>;
Returned
is the return type of the playlod generator and Arg
is the arguments type of the payload creator.
typePrefix
: prefix for generated Redux action type constants.
When typePrefix
is users/fetch
actions types are users/fetch
, users/fetch/pending
, users/fetch/fulfilled
and users/fetch/rejected
.
payloadCreator
: a generator that returns the payload to be put in fulfilled
action. It can yield any effects it needs.
1 function* (userId: string) { 2 const user: User = yield call(fetchUser, userId); // yield an effect 3 return user; // returns the result 4 },
A payloadCreator
can receive an arg. If you need to pass in multiple values, pass them together in an object when you dispatch the action.
options
: an object with the following optional fields:
condition
: a generator that can be used to skip execution of the payload creator. It can yield any effects but it returns a boolean. It receives arg payload creator as argument.dispatchConditionRejection
: by default if condition
returns false, nothing is dispatched. When dispatchConditionRejection
is set to true a "rejected" action is dispatched with meta.condition set to true.Actions are made of action itself, with is dispatched to trigger the async execution, and of createAsyncThunk's lifecycle actions: pending
, fulfilled
and rejected
.
action
:
1{ 2 type: `typePrefix`, // the typePrefix is given to createAsyncSaga 3 payload: arg, // object that contains the paylod creator arguments 4 meta: { 5 requestId: string // a uniqe id generatted for each execution 6 } 7}
pending
:
1{ 2 type: `typePrefix`/pending, // the typePrefix is given to createAsyncSaga 3 payload: undefined, // object that contains the paylod creator arguments 4 meta: { 5 arg, // object that contains the paylod creator arguments 6 requestId // id generated 7 } 8}
fulfilled
:
1{ 2 type: `typePrefix`/fulfilled, // the typePrefix is given to createAsyncSaga 3 payload: returned, // payload creator returned value 4 meta: { 5 arg, // object that contains the paylod creator arguments 6 requestId // id generated 7 } 8}
rejected
:
1{ 2 type: `typePrefix`/rejected, // the typePrefix is given to createAsyncSaga 3 payload: error, // a SerializedError made from what the payload creator thrown 4 meta: { 5 arg, // object that contains the paylod creator arguments 6 requestId // id generated 7 condition // true if rejected has been dispatched because condition has return false 8 } 9}
One can test the payload generator only or the saga returned by createAsyncSaga, although the full saga requires more stuff. In both case, test can be written using any Saga tests receipes.
A generator payload test (using redux-saga-test-plan):
1it('Test payload generator', () => { 2 const user: User = { 3 id: '123', 4 name: "John doe", 5 }; 6 testSaga(fetchUser, user.id) 7 .next() 8 .call(fetchUser, user.id) 9 .next(user) 10 .returns(user); 11});
A full saga test (still using redux-saga-test-plan):
1const fetchUserSaga = createAsyncSaga( 2 'users/fetch', 3 fetchUser 4); 5 6it('Test full saga', () => { 7 const user: User = { 8 id: '123', 9 name: "John doe", 10 }; 11 const action = fetchUserSaga.action(user.id); 12 const requestId = action.meta.requestId; 13 testSaga(fetchUserSaga.asyncSaga, action) 14 .next() 15 .put(fetchUserSaga.pending(user.id, requestId)) 16 .next() 17 .call(fetchUser, user.id) 18 .next(user) 19 .put(fetchUserSaga.fulfilled(user.id, requestId, user)) 20 .next() 21 .isDone(); 22});
This lib is new, and is missing some advanced functionalities (they will be added in the coming releases):
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
Found 0/30 approved changesets -- score normalized to 0
Reason
no SAST tool detected
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
11 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-14
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More