正确地“逐步”调用函数的方法

时间:2016-08-11 11:56:58

标签: javascript reactjs redux

我有某些功能要求我进行一次api调用以检索在第二次api调用中使用的某些id,逻辑上它看起来像这样:

componentWillMount () {
  this.props.functionOne()

  // Wait for functionOne to complete before calling this
  this.props.functionTwo(this.props.paramFromFunctionOne)
}

其中this.props.paramFromFunctionOne是一旦函数一完成就存储在redux状态的东西。

2 个答案:

答案 0 :(得分:2)

您可能希望使用redux-saga。 Redux saga专门用于调用异步函数和处理副作用。

例如,您可能希望在获取数据时在UI上显示加载程序图标。然后在收到数据后隐藏加载程序图标。您可以使用Redux-saga将此异步活动转换为同步活动。

saga示例 -

import { take, call, put, fork, cancel, race } from 'redux-saga/effects';
import { delay } from 'redux-saga';
import { LOCATION_CHANGE } from 'react-router-redux';
import { DATA_LOAD_REQUEST } from './constants';
import { dataLoadSuccess, dataLoadFailure } from './actions';

import request from 'utils/request'; //isomorphic-fetch

export function* getCompanies() {
  const requestURL = 'https://api.myjson.com/bins/32rap';
  const { companies, timeout } = yield race({
    companies: call(request, requestURL),
    timeout: call(delay, 10000),
  });

  if (companies) {
    yield put(dataLoadSuccess(companies.data));
  } else if (timeout) {
    yield put(dataLoadFailure());
  } else {
    yield put(dataLoadFailure());
  }
}

export function* getCompaniesWatcher() {
  while (yield take(DATA_LOAD_REQUEST)) {
    yield call(getCompanies);
  }
}

export function* companiesData() {
  const watcher = yield fork(getCompaniesWatcher);

  yield take(LOCATION_CHANGE);
  yield cancel(watcher);
}

// All sagas to be loaded
export default [
  companiesData,
];

起初,你可能会发现这令人难以置信。让我一点一点地解释一下。如果忽略redux-saga样板,你可以看到这段代码"看起来"绝对同步!

解密给定代码 -

  1. dataLoadRequest()发送到redux商店。 (在UI上显示加载程序)。

  2. 向API请求数据。

  3. 处理超时(如果数据未在10秒内加载,则会向redux商店发送dataLoadFailure()操作。
  4. 如果收到数据,请向商店发送dataLoadSuccess()操作。
  5. Redux-saga使用ES6生成器功能。 yield关键字是生成器函数的一部分。 function*表示它是生成器函数而不是正常的javascript函数。

    希望这会有所帮助。祝你好运!

答案 1 :(得分:2)

正如我所理解的那样,你可以这样做:

componentWillMount () {
  // As `axios` returns promise, you should return it from `functionOne`
  // This way you can be able to use `.then` method.
  this.props.functionOne()
    .then(() => {
      // This code block would be executed after api call from first function will be finished.
      this.props.functionTwo(this.props.paramFromFunctionOne)
    });
}