Skip to content

Instantly share code, notes, and snippets.

@beautyfree
Created January 30, 2018 12:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beautyfree/690d6b1037f79547e3d5bcd1d30bcc63 to your computer and use it in GitHub Desktop.
Save beautyfree/690d6b1037f79547e3d5bcd1d30bcc63 to your computer and use it in GitHub Desktop.
call api saga queue
import { take, takeEvery, put, all, fork, call } from 'redux-saga/effects'
import { channel, delay, select } from 'redux-saga'
import { callApi, CALL_API } from 'redux/services'
const REQUESTS_COUNT = 3
const REQUESTS_DELAY = 1000
class RequestsBuffer {
constructor() { this.queue = [] }
isEmpty = () => !this.queue.length
put = (message) => this.queue.push(message)
take = () => {
const buff = this.queue.slice(0, REQUESTS_COUNT)
this.queue = this.queue.slice(REQUESTS_COUNT)
return buff
}
}
export function* watchRequests() {
// create a channel to queue incoming requests
const chan = yield call(channel) //, new RequestsBuffer())
yield fork(processChannel, chan)
yield takeEvery(CALL_API, function*(action) {
// dispatch to the worker thread
yield put(chan, action)
});
}
function* processChannel(chan) {
let working = 0
while (true) {
const actions = yield take(chan);
working++
if(Array.isArray(actions)) {
yield all(actions.map((action) => fork(handleRequest, action)));
} else {
yield fork(handleRequest, actions)
}
if (working === REQUESTS_COUNT) {
yield delay(REQUESTS_DELAY)
working = 0
}
}
}
function* handleRequest(action) {
let { method, endpoint } = action.payload;
const { schema, types, data } = action.payload;
if (!method) {
method = 'GET';
}
if (typeof endpoint === 'function') {
endpoint = endpoint(select());
}
if (typeof method !== 'string') {
throw new Error('Specify a string method type.');
}
// if (!Object.keys(requestEnum).some(key => key === method)) {
// throw new Error('Expected method type to be one of ' + Object.keys(requestEnum) + ' types.');
// }
if (typeof endpoint !== 'string') {
throw new Error('Specify a string endpoint URL.');
}
// if (!schema) {
// throw new Error('Specify one of the exported Schemas.');
// }
if (!Array.isArray(types) || types.length !== 3) {
throw new Error('Expected an array of three action types.');
}
if (!types.every(type => typeof type === 'string')) {
throw new Error('Expected action types to be strings.');
}
function actionWith(data) { // eslint-disable-line
const finalAction = Object.assign({}, action, data);
delete finalAction[CALL_API];
return finalAction;
}
const [requestType, successType, failureType] = types;
yield put(actionWith({ type: requestType }));
const { response, error } = yield callApi(method, endpoint, data, schema)
// console.log(response, error)
if(response) {
yield put(actionWith({
payload: response,
type: successType,
}))
} else {
yield put(actionWith({
type: failureType,
error: error || 'Something bad happened',
}))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment