【问题标题】:redux saga ajax call - not working as expectedredux saga ajax 调用 - 未按预期工作
【发布时间】:2018-06-28 23:19:02
【问题描述】:

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

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响应成功返回,当流程进入reducer的FIRST_REQUEST_FAIL部分并且数据显示为错误时,我正在错误中获取数据。

这是reducer的代码 流向哪里

case 'FIRST_REQUEST_FAIL':
      return {

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

而不是去

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

那么,这里的代码有什么问题?为什么服务器响应成功后仍然显示错误?

【问题讨论】:

    标签: ajax reactjs promise redux-saga


    【解决方案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

    【讨论】:

    • 你能解释一下为什么你推荐 axios 或 fetch 而不是 ajax 吗?
    • 好吧,我使用了 fetch,它确实帮助解决了这个问题。但我仍然不确定为什么 ajax 在这里不起作用。即使我从 ajax 请求中删除了成功部分。
    • AFAIK,jQuery返回的promise是自定义的Promise,不是浏览器默认使用的,参数定义有误
    【解决方案2】:

    这是一种使用 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);
         //...
       }
      }
    

    使用这种结构,您应该能够在提出请求时捕捉到您的成功和错误。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    相关资源
    最近更新 更多