Sergei Klinov
Sergei Klinov

Reputation: 798

Redux-Saga call() and put() in map

I'm trying to make several requests using all() and map() functions and if result comes and have the expected shape, I want to call another action to save the result in my store.

Here's a part of my saga, but it's not working as expected - the getAvailabilityRequest is not executed.

   yield all(
    part1.map((p1) => {
      return part2.map((p2) => {
        return tld.map((t) => {
          const response =  call(getAvailabilityRequest, `${p1}${p2}.${t}`);
          if (response && isAvailabilityResult(response)) {
              const index: AvailabilityIndex = { part1: p1, part2: p2, tld: t };
              return put(setAvailabilityActionCreator({ index, item: response }));
            }
        });
      });
    })
  );

Also I've tried this

  const response = yield all(
    part1.map((p1) => {
      return part2.map((p2) => {
        return tld.map((t) => {
          return {index: { part1: p1, part2: p2, tld: t }, result: call(getAvailabilityRequest, `${p1}${p2}.${t}`)};
        });
      });
    })
  );

to keep the data about index, but still, getAvailabilityRequest is not being called. Is there a way I can change the saga to get expected results?

Upvotes: 0

Views: 1806

Answers (1)

kind user
kind user

Reputation: 41893

You are not returning the call so it can't be yielded. What's more important - yield all expects an array of functions that return Promises. Dispatching an action doesn't return a Promise and this is what you are doing here. put are a non-blocking calls.

I'd suggest you to delegate the logic to a separate generator function.

function* getAvailability(p1, p2, t) {
   try {
      const response = call(getAvailabilityRequest, `${p1}${p2}.${t}`);
      if (response && isAvailabilityResult(response)) {
          const index: AvailabilityIndex = { part1: p1, part2: p2, tld: t };
          yield put(setAvailabilityActionCreator({ index, item: response }));
      }
   } catch (error) {
     // error logic
   }
}

Edit: It seems like the nested map is an issue. yield all expects a flat array.

const calls = yield [];

yield part1.forEach((p1) => {
   part2.forEach((p2) => {
      tld.forEach((t) => {
         calls.push(call(getAvailabilityRequest, `${p1}${p2}.${t}`));
      });
   });
});


const response = yield all(calls);

Upvotes: 1

Related Questions