2

This code is inside a redux saga file.

I'm trying to send the response back to the saga function but I can't.

new GraphRequestManager().addRequest(infoRequest).start();
infoRequest = new GraphRequest(
    '/me', {
        httpMethod: 'GET',
        version: 'v2.5',
        parameters: {
            'fields': {
                'string': 'email,first_name,last_name,id'
            }
        }
    }, startFacebookRegister);

the facebookRegister function

function * startFacebookRegister(err, res) {
    const { id, email, first_name, last_name } = res;
    yield put(initFacebookLogin.success(res));
}
Matt Stobbs
  • 611
  • 2
  • 8
  • 21

1 Answers1

0

If we look at GraphRequestManager.start.

    const that = this;
    const callback = (error, result, response) => {
      if (response) {
        that.requestCallbacks.forEach((innerCallback, index, array) => {
          if (innerCallback) {
            // here it is called as a normal callback, not a generator
            innerCallback(response[index][0], response[index][1]);
          }
        });
      }
      if (that.batchCallback) {
        that.batchCallback(error, result);
      }
    };

    NativeGraphRequestManager.start(this.requestBatch, timeout || 0, callback);   } ```

The callback you pass is invoked as a normal Function, as opposed to a GeneratorFunction.

And since they differ in how they are executed, that's why nothing happens, since your GeneratorFunction, when invoked, is just instantiated and sits there until getting garbage collected.

So the preferred option to solve this, which is aligned with the redux-saga flow is using eventChannel, which keeps the flow inside redux-saga and is actually advised for similar cases.

The other one, not so preferable, would be to just call raw store.dispatch, it obviously breaks through the abstraction levels and flow of redux-saga, but still gets the job done, by invoking some other saga action which can handle calling your startFacebookRegister with the response.

EventChannel

We need to wrap the whole GraphRequestManager... block into an eventChannel, so we can redirect the response or error back into saga flow from the vendor control.

Can be something like this:

import {
  cancelled,
  call,
  take,
  put
} from "redux-saga/effects";

import {
  eventChannel,
  END
} from 'redux-saga';

function* startFacebookRegister(err, res) {
  const {
    id,
    email,
    first_name,
    last_name
  } = res;
  yield put(initFacebookLogin.success(res));
}

function* graphRequestWrapper() {
  return eventChannel(emit => {
    const infoRequest = new GraphRequest(
      '/me', {
        httpMethod: 'GET',
        version: 'v2.5',
        parameters: {
          'fields': {
            'string': 'email,first_name,last_name,id'
          }
        }
      }, (err, res) => {
        if (err) {
          emit(new Error(err));
        } else {
          emit(res);
        }

        emit(END);
      });

    // BTW infoRequest variable should be instantiated before we
    // can add it with addRequest, just a side note
    new GraphRequestManager().addRequest(infoRequest).start();

    return () => {
      // clean up
    };
  })
}


export function* mainSaga() {
  const chan = yield call(graphRequestWrapper);

  while (true) {
    try {
      const res = yield take(chan);
      yield call(startFacebookRegister, null, res);
    } catch (err) {
      yield call(startFacebookRegister, err);
    } finally() {
      if (yield cancelled()) chan.close()
    }
  }

}

Store Dispatch

And with store, you can export your store from your main.js or index.js where you createStore it with all the reducers and middlewares, and use it here directly.

import store "../exported/from/somewhere";

function* startFacebookRegister({payload}) {
  const {
    id,
    email,
    first_name,
    last_name
  } = payload;
  yield put(initFacebookLogin.success(res));
}

function graphRequestWrapper() {
  const infoRequest = new GraphRequest(
    '/me', {
      httpMethod: 'GET',
      version: 'v2.5',
      parameters: {
        'fields': {
          'string': 'email,first_name,last_name,id'
        }
      }
    }, (err, response) => {
      store.dispatch({type: "INIT_FACEBOOK_LOGIN_REQUEST_SUCCESS_SAGA", payload: {...response}})
    });

  new GraphRequestManager().addRequest(infoRequest).start();
}

function* mainSaga() {
  yield takeLatest("INIT_FACEBOOK_LOGIN_REQUEST_SUCCESS_SAGA", startFacebookRegister);

  yield call(graphRequestWrapper);
}
Karen Grigoryan
  • 5,234
  • 2
  • 21
  • 35