redux saga ajax call - 没有按预期工作

时间:2018-01-19 16:45:20

标签: ajax reactjs promise redux-saga

我有这个redux传奇代码,其中一切正常......直到承诺,之后事情开始出错 这里是相关代码

const firstApiRequest = ()=>{
  return $.ajax({
    url: myUrl,// ,
    type:'POST',
    headers: {
        "Accept":"application/json",
        "Content-Type":"application/json",
    },
    data:JSON.stringify(bodyData),
       success:function(res){
          console.log(res);
          return res;
       }
    })
};



export function *startCheckout() {
    try {
        yield put(showLoading());
        const data = yield call(firstApiRequest);//const data ends
        yield put({type:FIRST_REQUEST_DONE,payload:data});           
    } catch (err) {
        yield put(firstRequestFail(err));
    }
}

export function *checkout() {
      yield takeEvery(SEND_FIRST_REQUEST, startCheckout);
}

问题是在firstApiRequest中的return res之后,我想使用data发送FIRST_REQUEST_DONE操作,但会发生的是流程转到FIRST_REQUEST_FAIL并显示错误为真。 问题是api响应成功返回,当流程转到减速器的FIRST_REQUEST_FAIL部分并且数据显示为错误时,我在错误中获取数据。

这里是reducer的代码 流向哪里

case 'FIRST_REQUEST_FAIL':
      return {

        loading: false,
        error: true,
        errorMessage: action.err,
      };

而不是去

case 'FIRST_REQUEST_DONE':
      return {
        id: action.id,
      };

那么,这里的代码有什么问题?为什么即使在服务器成功响应后它也显示错误?

2 个答案:

答案 0 :(得分:1)

您不应该在api请求中定义success。 $ .ajax将自行返回一个承诺:

const firstApiRequest = () => (
  $.ajax({
    url: myUrl,// ,
    type:'POST',
    headers:{
        "Accept":"application/json",
        "Content-Type":"application/json",
    },
    data:JSON.stringify(bodyData),
}));

另外,为什么使用jQuery来发出API请求?我建议使用axiosfetch

答案 1 :(得分:0)

以下是使用redux-saga处理API请求的方法:

首先创建一个请求助手

import 'whatwg-fetch';

function parseJSON(response) {
 return response.json ? response.json() : response;
}

/**
 * Checks if a network request came back fine, and throws an error if 
   not
 *
 * @param  {object} response   A response from a network request
 *
 * @return {object|undefined} Returns either the response, or throws an 
 * error
*/
 function checkStatus(response, checkToken = true) {
   if (response.status >= 200 && response.status < 300) {
     return response;
  }

 return parseJSON(response).then(responseFormatted => {
   const error = new Error(response.statusText);
   error.response = response;
   error.response.payload = responseFormatted;
   throw error;
 });
}

/**
 * Requests a URL, returning a promise
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 *
 * @return {object}           The response data
*/
export default function request(url, options = {}) {
// Set headers
  if (!options.headers) {
    options.headers = Object.assign({
     'Content-Type': 'application/json',
   }, options.headers, {});
  }

 // Stringify body object
 if (options && options.body) {
   options.body = JSON.stringify(options.body);
 }

 return fetch(url, options)
  .then(checkStatus)
  .then(parseJSON)
}

在你的传奇中

import { call, fork, put, takeLatest } from 'redux-saga/effects';
import request from 'utils/request';

import { submitSuccess, submitError } from './actions'; // path 
to your actions.

import { SUBMIT } from './constants'; // The event you're listening

export function* submitData(action) {
  try {
    const response = yield call(request, 'your_url', { method: 'POST', body: action.body });
    yield put(submitSuccess(response));
  } catch(err) {
     yield put(submitError(response.payload.message);
  }
}

export function* defaultSaga() {
  yield fork(takeLatest, SUBMIT, submitData);
}

export default defaultSaga;

<强>减速

const initialState = fromJS({
  submitSuccess: false,
  submitReponse: '',
  errorMessage: '',
});

 function fooReducer(state = initialState, action) {
   switch (action.type) {
     case SUBMIT_SUCCESS:
       return state
         .update('submitSuccess', () => true)
         .update('submitResponse', () => action.response);
     case SUBMIT_ERROR:
       return state.update('errorMessage', () => action.errorMessage);
     //...
   }
  }

通过这种结构,您应该能够抓住您的成功,并在您提出请求时出错。