在 Meteor.call 之后在 saga watcher 中调度动作

dispatch action inside saga watcher after Meteor.call

我想在 Meteor.call 回调中调度操作。

我试过将生成器函数作为回调传递,但没有用。

function* createRegistrationField(action: CreateRegistrationFieldRequest) {
  yield call(function* () {
    yield put(CreateRegistrationFieldRequestRunningAction());
  });

  const { type } = action.payload;

  const callBack = function*(error, _id) {
    console.log("callback called");

    yield put(RegistrationFieldCreatedAction(type, _id));
  };

  Meteor.call("registerFormFields.insert", { type }, callBack);
};


export function* watchCreateRegistrationField() {
  yield takeLatest(CREATE_REGISTRATION_FIELD_REQUEST, createRegistrationField);
};

registerFormFields.insert 长得像

  Meteor.methods({
    "registerFormFields.insert" (data: object) {
      return RegisterFormFields.insert(data);
    },
    "registerFormFields.list" () {
      return RegisterFormFields.find({}).fetch();
    }
  });

我找到了自己的解决方案。

在 redux-saga 中我们有 eventChannel.

这是我如何操作的示例。

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

function createRegistrationFieldChannel(type: string) {
  return eventChannel(emitter => {
    Meteor.call("registerFormFields.insert", { type }, (error, _id) => {
      if (error) {
        emitter({ error });
        emitter(END);
      }

      emitter({ _id });
      emitter(END);
    });

    return () => {};
  });
}

function* createRegistrationField(action: CreateRegistrationFieldRequest) {
  yield call(function*() {
    yield put(CreateRegistrationFieldRequestRunningAction());
  });

  const { type } = action.payload;

  const channel = yield call(createRegistrationFieldChannel, type);

  try {
    while (true) {
      const { error = null, _id } = yield take(channel);

      if (error) {
      } else {
        yield put(RegistrationFieldCreatedAction(type, _id));
      }
    }
  } catch (err) {
    console.log(err);
  }
}

export function* watchCreateRegistrationField() {
  yield takeLatest(CREATE_REGISTRATION_FIELD_REQUEST, createRegistrationField);
}