redux-saga: почему `yield call (func, params)` терпит неудачу, но `yield call (() => func (params))` завершается успешно? - PullRequest
0 голосов
/ 12 января 2019

Вот мой код, который заканчивается в строке с комментарием //fails:

import {API} from "aws-amplify";

function* watchSitesRequested(dispatch) {
  const watchAction = ('SITES_FETCH_REQUESTED');
  const APIname="MyAPIGatewayAPI";
  const APIpath="/configmagic/sites";
  const APIinit={
    headers: {
      'Accept': 'application/json'
    },
    response: true,
  };
  while (true) {
    yield take(watchAction);
    try {
      const request = yield call(API.get, APIname, APIpath, APIinit); //fails
      yield put({type: "SITES_FETCH_SUCCEEDED", payload: {sites: request.data}});
    } catch (e) {
      yield put({type: "SITES_FETCH_FAILED", message: e.message})
    }
  }
}

Ошибка консоли:

TypeError: Cannot read property '_api' of null
    at API.js:298
    at step (API.js:137)
    at Object.next (API.js:67)
    at API.js:39
    at new Promise (<anonymous>)
    [snip]

Но если я изменю вызов API.get следующим образом, он будет вести себя как нужно:

const request = yield call(() => API.get(APIname, APIpath, APIinit))

Почему?

yield call() Я думаю, что должен принимать несколько параметров после функции, и он должен нормально работать с Promise, который возвращает API.get(), не так ли?

1 Ответ

0 голосов
/ 12 января 2019

Вы должны назвать это так:

const request = yield call([API, API.get], APIname, APIpath, APIinit)

или

const request = yield call([API, 'get'], APIname, APIpath, APIinit)

Это потому, что API является экземпляром класса APIClass.

В Javascript есть безумные правила передачи this при вызове метода экземпляра. По сути, он работает только так, как задумано, когда вы непосредственно пишете API.get() в коде. Но когда вы планируете вызов с помощью эффекта call, объект эффекта сохраняет только ссылку на функцию API.get, теряя ссылку this.

Чтобы правильно передать this, вы должны использовать call([context, fn], ...args).

...