title: Redux-saga: [...effects] has been deprecated in favor of all([...effects]), please update your code
body: <p>I've upgraded redux-saga to the latest 0.15.x release, and I've tackled a lot of deprecations in terms of  <code>[...effects] has been deprecated in favor of all([...effects]), please update your code</code></p>
  
  <p>There is only one deprecation left, and I've identified it in this part of the code. Can anyone take a look at the code below and point out how it triggers the deprecation?</p>
  
  <p>I've tried following the instructions in the <a href="https://github.com/redux-saga/redux-saga/releases/tag/v0.15.0" rel="nofollow noreferrer">https://github.com/redux-saga/redux-saga/releases/tag/v0.15.0</a> changelog:</p>
  
  <p><code>all effect - explicit effect for parallel effects, which is exactly what we had been supporting by accepting yielded arrays, so the latter is become deprecated now in favor of this explicitness which nicely maps to the Promise.all API. Please use this from now on</code></p>
  
  <p>This is the relevant code:</p>
  
  <pre><code>import { call, put, race, take, takeEvery } from 'redux-saga/effects';
  import {
    BATCH_START,
    BATCH_SUCCESS,
    BATCH_FAIL,
    SUB_BATCH_START,
    SUB_BATCH_SUCCESS,
    SUB_BATCH_FAIL
  } from 'redux/modules/batch/constants';
  
  /*
    This method is required to prevent additional takes.
  */
  export function* takeFirstOccurrence(fn) {
    const res = yield take(fn);
    return res;
  }
  
  export const takeSuccess = (c) =&gt; (b) =&gt; b.type === `${c.type}_SUCCESS` &amp;&amp; b.batchId === c.batchId;
  export const takeFail = (c) =&gt; (b) =&gt; b.type === `${c.type}_FAIL` &amp;&amp; b.batchId === c.batchId;
  
  export function* batchRequest(action, results = {}) {
    const { batchId, actions } = action;
    try {
      const racer = {};
      const takes = [];
      const keysToSuccess = [];
  
      // Actions must be array
      for (let i = 0; i &lt; actions.length; i++) {
        let c = actions[i];
  
        if (Array.isArray(c)) {
          const currentBatchId = `${batchId}.${i}`;
          yield put({ type: SUB_BATCH_START, batchId: currentBatchId });
          const res = yield call(batchRequest, { actions: c, batchId: currentBatchId }, results);
          // if the subbatch return object has an error property then everything has gone to shit. Fail the batch/sub-batch. Pass the object up the chain, so the fail reaches the root batch
          if (res.error) {
            results = {
              ...results,
              error: res.error
            };
            // An error has occurred, so hop out of the loop so the parent batch can fail immediately
            // ...or not, for now, since later batches may contain required error logic.
            // i = actions.length;
          } else {
            // update results such that the next array to be called with call(batchRequest...) gets the new results to pass to it's child actions.
            results = {
              ...results,
              ...res
            };
          }
        } else {
          // The batcher expects an object for each action, with one key, the name to associate with the success or error of the action
          const key = Object.keys(c)[0];
          c = c[key];
          // The single property can be either an action object, or a function that returns an action object. If it is a function, it is passed the current results object
          if (typeof c === 'function') {
            c = c(results);
          }
          if (c) {
            c.batchId = `${batchId}.${key}`;
            if (/.*_REQUEST$/.test(c.type)) {
              racer[key] = take(takeFail(c));
              takes.push(takeFirstOccurrence(takeSuccess(c)));
              keysToSuccess.push(key);
            }
            if (c.type) yield put(c);
          }
        }
      }
      // if the "takes" array has no entries then, by definition, the requests are all synchronous and must succeed. There is no return data, so send empty obj with empty success key
      let returnObj = {};
      // if "takes" has entries then the batch/sub-batch contains at least 1 asynchronous action
      if (takes.length &gt; 0) {
        const { success, ...errors } = yield race({
          success: takes,
          ...racer
        });
        // if any of the errors wins the race, then the success property is undefined. Return obj with error property, it will fail the batch/sub-batch.
        if (!success) {
          returnObj = { error: errors };
        } else {
          // else transfer the success array into an object, mapping them in order to the keysToSuccess array constructed eariler
          const successAsKeys = {};
          success.forEach((s, i) =&gt; {
            successAsKeys[keysToSuccess[i]] = s;
          });
          returnObj = successAsKeys;
        }
      }
      results = {
        ...results,
        ...returnObj
      };
      // either we reach this point because there are no takes and the batch must succeed, or we exited a loop of arrays, and need to check if there is an error on the results added during that
      if (results.error) {
        yield put({ type: batchId.indexOf('.') === -1 ? BATCH_FAIL : SUB_BATCH_FAIL, batchId, data: results });
      } else {
        yield put({ type: batchId.indexOf('.') === -1 ? BATCH_SUCCESS : SUB_BATCH_SUCCESS, batchId, data: results });
      }
      return results;
    } catch (error) {
      console.log(error);
    }
  }
  
  export default function batchListener() {
    return function* actionListener() {
      return yield takeEvery(action =&gt; action.type === BATCH_START &amp;&amp; action.batchId, batchRequest);
    };
  }
  </code></pre>