Enes ÜNAL
Enes ÜNAL

Reputation: 31

redux saga multiple calls make next one when the other fails

I have a saga makes multiple call in it:

function* membersInfoSaga({ payload }) {
    const endpoints = [
        api.fetchNotifications,
        api.fetchPosts,
        api.fetchMessages,
        api.fetchActivities
    ]

    const responses = yield all(endpoints.map(endpoint => {
        try {
            return call(endpoint, payload.memberId, payload.page, payload.pageSize)
        } catch (error) {
            return { data: {} }
        }
    }))

When a call gets 400 as a response, i want it to continue for the others and return { data: {} } for the failed call.

I am making calls with Fetch API. And here is my api.js:

function callApi(endpoint, options, unauthorized, isRefreshToken) {
    const URL = BASE_URL + endpoint
    const ACCESS_TOKEN = localStorage.getItem("access_token")
    if (!options) options = {}

    options["headers"] = {
        "Content-Type": "application/json",
        "Accept": "application/json"
    }

    if (!unauthorized) {
        options.headers["Authorization"] = `Bearer ${ACCESS_TOKEN}`
    }

    return fetch(URL, options)
        .then((response) => response.json())
        .then((response) => {
            if (response.code >= 200 && response.code <= 299) {
                return Promise.resolve(response)
            } else if (response.code === 401) {
                if (isRefreshToken) {
                    store.dispatch({ type: actionTypes.AUTH_REFRESH_FAILED })
                } else {
                    store.dispatch({
                        type: actionTypes.INVALID_TOKEN,
                        payload: { error: response.error.message }
                    })

                    return { error: response.error.message }
                }
            } else {
                return Promise.reject(response.error.message)
            }
        })
        .catch((error) => {
            return Promise.reject(error)
        })
}

And this is the function that i invoke inside saga call method:

const fetchNotifications = (memberId, page, pageSize) => callApi(`notifications/${memberId}?page=${page}&page_size=${pageSize}`)

Upvotes: 3

Views: 1484

Answers (2)

Enes &#220;NAL
Enes &#220;NAL

Reputation: 31

I have fixed this a little bit different. I've made some updates on my saga and now i can make multiple calls even if some of them returns 400 as response. Here is my solution:

function* fetchMembersInfo(payload) {
    yield fork(membersNotificationsSaga, { payload })
    yield fork(membersPostsSaga, { payload })
    yield fork(membersMessagesSaga, { payload })
    yield fork(membersActivitesSaga, { payload })
}

const getNotifications = state => state.members.selectedAccount.notifications.data.notifications
const getPosts = state => state.members.selectedAccount.posts.data.posts
const getMessages = state => state.members.selectedAccount.messages.data.messages
const getActvities = state => state.members.selectedAccount.activites.data.activities

function* membersInfoSaga({ payload }) {
    try {
        yield call(fetchMembersInfo, payload)

        const notifications = yield select(getNotifications)
        const posts = yield select(getPosts)
        const messages = yield select(getMessages)
        const activites = yield select(getActivities)
        ...
    } catch (error) {
        ...
    }
}

Upvotes: 0

Martin Kadlec
Martin Kadlec

Reputation: 4975

The problem in your code is that the try..catch is where you call the call effect creator, but not where you yield the resulting effect object. Of course you can't yield directly inside an arrow function either. The way to get around this is to wrap the try..catch in additional saga generator that will then get executed by the all effect.

  const responses = yield all(
    endpoints.map((endpoint) => {
      return call(function* () {
        try {
          return yield call(endpoint, payload.memberId, payload.page, payload.pageSize);
        } catch (error) {
          return { data: {} };
        }
      });
    })
  );

Upvotes: 1

Related Questions