2017-05-31 60 views
1

我正在開發一個應用程序,其中有很多異步操作。我想用最簡單的方法去解決,但是大多數人都堅持要繼續進行縮減。在redux-thunk中,在每個動作中,我們必須使用異步操作,然後使用dispatch,catch,等等。這使得看起來很麻煩,很多代碼會重複。我想創建一個通用的數據加載器來使用redux-thunk和axios,但不能考慮這兩個帖子(可能是令牌或不),並獲得選項。使用axios的redux-thunk的通用dataloader

這裏是我的嘗試:

export class Company { 
/** 
* Generic api data loader 
*/ 
static dataLoader(apiUri, onSuccess, onError, data, ...actionArguments) { 
    const requestURL = `${API_BASE}${apiuri}`; 
    try { 
    let options; 
    if (data !== undefined) { 
     // if we have data to post 
     options = { 
     method: 'POST', 
     url: requestURL, 
     body: JSON.stringify(data), 
     headers: { 
     'Content-Type': 'application/json', 
     'X-Requested-With': 'XMLHttpRequest', 
     }, 
     }; 
    } 
    } 
    return function(dispatch) { 
    axios(options) 
    .then(response => { 
     dispatch({ 
     type: onSucess, 
     payload: response.data 
     }); 
    }) 
    .catch(error => { 
     dispatch({ type: onError, payload: err}); 
    }); 
    } 
} 

static get(apiUri, onSuccess, onError, ...actionArguments) { 
    return this.dataLoader(apiUri, onSuccess, onError, undefined, ...actionArguments); 
    } 

    /* 
    * Shorthand POST function 
    */ 
    static post(apiUri, onSuccess, onError, data, ...actionArguments) { 
    return this.dataLoader(apiUri, onSuccess, onError, data, ...actionArguments); 
    } 

} 

我想下面的代碼轉化爲推動這一之一:

export function showResultofApartment() { 
    return (dispatch) => { 
    dispatch({ type: 'APARTMENT_FETCH_START' }); 
    const token = localStorage.getItem('token'); 
    return axios.get(`${API_URL}/newoffers/apartment/`) 
    .then((response) => { 
     console.log('response apart', response.data); 
     dispatch({ type: 'APARTMENT_FETCH_SUCCESS', payload: response.data }); 
    }) 
    .catch((err) => { 
     dispatch({ type: 'APARTMENT_FETCH_FAILURE', payload: err }); 
    }); 
    }; 
} 

本這樣或效率比:

export function showResultofApartment() { 
    return(dispatch) => { 
    dispatch({ type: APARTMENT_FETCH_START }); 
    const token = localStorage.getItem('token'); 
    return Company.get('/apartments', APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR); 
    // if post then Company.post('/apartment', APARTMENT_POST_SUCCESS, APARTMENT_POST_ERROR, data) 
    } 
} 

這樣它只考慮發佈請求(如果數據!==未定義)。我應該如何處理得到和有效的後?

+0

爲了避免產生更多混淆,我認爲在您有多個同步或異步axios請求處理的情況下,redux-saga會更加優雅。如果您有興趣,我可以發佈我們公司遵循的模式。 –

+0

如果我知道你使用的模式,我會很感激你,但同時我希望這個與這個項目的最佳結合。這將是我們最後一次使用redux-thunk。爲了繼續這個項目,我必須堅持不懈。你能幫我解決一般的dataLoader問題嗎? – Serenity

回答

1

好了,你爲什麼不處理它是這樣的:

Company.js

import { merge } from 'lodash'; 
import axios from 'axios'; 

function getHeaders() { 
    return { 
    'Content-Type': 'application/json' 
}; 
} 

export class Company { 

static callAPI(endpoint, extendedOptions, onSuccess, onError) { 
    const initalHttpData = { 
    method: 'GET', // By default it's GET in case you didnt specify anything 
    headers: getHeaders(), 
    url: `${API_BASE}${endpoint}` 
    }; 

    // merge takes care of replacing or adding the specific key's provided via the extendedOptions 
    const options = merge(initalHttpData, extendedOptions); 

    // Fire the request for the prepared options. 
    let request = axios(options); 

    // The request once fired, needs it's success handler and error handler. 
    return function(dispatch) { 
    request 
    .then(response => { 
     dispatch({ 
     type: onSucess, 
     payload: response.data 
     }); 
    }) 
    .catch(error => { 
     dispatch({ type: onError, payload: err}); 
    }); 
    } 
}; 
} 

然後我們可以用行動來具體的東西傳遞給這個API UTIL:

GET API撥打:

// GET Action 
export function showResultofApartment() { 
    return (dispatch) => { 
    dispatch({ type: APARTMENT_FETCH_START }); 
    const token = localStorage.getItem('token'); 

    // FOR GET API 
    return Company.callApi('/apartments', {}, APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR); 
    } 
} 

POST API調用:

// POST Action 
export function showResultOfAppartmentPost() { 
    return (dispatch) => { 
    dispatch({ type: APARTMENT_FETCH_START }); 
    const token = localStorage.getItem('token'); 

    // This will merge, essentially replace the method=GET once it gets called. 
    const extendedOptions = { 
     method: 'POST', 
     body: JSON.stringify(data), 
     headers: { 
     'X-Requested-With': 'XMLHttpRequest', 
     } 
    } 

    // FOR GET API 
    return Company.callApi('/apartments', extendedOptions, APARTMENT_FETCH_SUCCESS, APARTMENT_FETCH_ERROR); 
} 

因此,給出操作,定義它自己的一組API主體或請求。

+0

衷心感謝您的親切幫助,我感謝您的努力。一個問題,是不是合併變異的對象?我們不能只做Object.assign({},initalHttpData,extendedOptions)嗎? – Serenity

+0

@Serenity我使用Lodash庫:https://lodash.com/docs/#merge,其實質上是對象分配與深入比較 –

+0

我試過用Object.assign(),但得到了錯誤404沒有找到不能OPTIONS/api/。這是由於Object.assign()引起的錯誤嗎? – Serenity