Redux

2016-04-17 27 views
8
में कई async प्रेषण चेनिंग

मैं श्रृंखला अनेक कार्रवाइयों के लिए एक साथ निम्नलिखित फैशन में कोशिश कर रहा हूँ: डेटाबेस के लिएRedux

उपयोगकर्ता ए पोस्ट डेटा

बी उपयोग डेटा तैनात परिणाम

के लिए Elasticsearch क्वेरी करने के लिए

(मैं समानांतर में ए और बी करता हूं)

बी 1। ईएस के परिणामों के साथ, दो टेबल बी 2 के परिणामों के लिए मूल डेटाबेस क्वेरी करें। नया पृष्ठ और अद्यतन यूआई

मैं Thunks उपयोग कर रहा हूँ अभी मेरी कोड के बारे में तर्क करने के लिए नेविगेट, लेकिन मैंने यह भी पाया इस async पद्धति अत्यंत वर्बोज़ होने के लिए: "requestRecipes" के साथ इस,

export function fetchRecipes(request) { 
    return function(dispatch) { 
    dispatch(requestRecipes(request))  
    return fetch(url) 
     .then(response => response.json()) 
     .then(json => dispatch(receiveRecipes(request, json)) 
    ) 
    } 
} 

और "getRecipes" के रूप में अन्य एक्शन क्रिएटर एक एसिंक कॉल करने के लिए बस थोड़ा सा लगता है। (एक अनुरोध, प्राप्त, और एक fetch समारोह)

सारांश: जब आप 2-3 एसिंक क्रियाओं को चेन कर रहे हैं जिनके आउटपुट एक-दूसरे पर निर्भर करते हैं (मुझे संभव होने पर प्रचार करने की आवश्यकता है), क्या वहां एक और अधिक प्रभावी साधन हैं प्रत्येक async कॉल के लिए 3 कार्यों को लिखने के बिना ऐसा कर रहे हैं?

मुझे लगता है कि वहां एक तरीका होना चाहिए था। मैं रेडक्स डॉक्स से मिलान करने वाला पैटर्न हूं और जल्द ही उन कार्यों के साथ बहुत अभिभूत हो गया जो मैं

प्रतिक्रिया के लिए बहुत बहुत धन्यवाद!

+0

मैं इस पैटर्न का उपयोग करता हूं; यह बहुत सारे फ़ंक्शन हैं, लेकिन आप एक ऐसा कारखाना भी बना सकते हैं जो आपके ऐप के शुरू होने के बाद आपके लिए उन सभी कार्यों को बनाएगा। उदाहरण के लिए, प्रतिक्रिया-redux-universal में [इस midware] देखें (https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/redux/middleware/clientMiddleware.js) -शॉट-उदाहरण (मुझे उस उदाहरण रेपो में विभिन्न पैटर्न से बहुत प्रेरणा मिलती है)। साथ ही, मैं इसे एसिंक क्रियाओं के संदर्भ में रेडक्स का उपयोग करने का एक सही तरीका नहीं मानता; मैं यहां अन्य प्रतिक्रियाओं को देखने के लिए उत्सुक हूं। – mjohnsonengr

उत्तर

8

आप इसे और अधिक आसानी से प्राप्त करने के लिए redux-thunk के बजाय redux-saga का उपयोग कर सकते हैं। redux-saga आपको जेनरेटर का उपयोग करके अपने काम का वर्णन करने देता है और इसके बारे में तर्क करना आसान है।

पहला कदम यह वर्णन करना है कि आप सेवाओं या एसिंक सामग्री के बारे में चिंता किए बिना अपने डेटा को रेडक्स में कैसे पास करते हैं।

क्रिया

// actions.js 
function createRequestTypes(base) { 
    return { 
    REQUEST: base + "_REQUEST", 
    SUCCESS: base + "_SUCCESS", 
    FAILURE: base + "_FAILURE", 
    } 
} 

// Create lifecycle types on `RECIPES` 
export const RECIPES = createRequestTypes("RECIPES") 

// Create related actions 
export const recipes = { 
    // Notify the intent to fetch recipes 
    request: request => ({type: RECIPES.REQUEST, request}) 
    // Send the response 
    success: response => ({type: RECIPES.SUCCESS, response}) 
    // Send the error 
    error: error => ({type: RECIPES.FAILURE, error}) 
} 

प्रसारण

// reducer.js 
import * as actions from "./actions" 

// This reducer handles all recipes 
export default (state = [], action) => { 
    switch (action.type) { 
    case actions.RECIPES.SUCCESS: 
     // Replace current state 
     return [...action.response] 

    case actions.RECIPES.FAILURE: 
     // Clear state on error 
     return [] 

    default: 
     return state 
    } 
} 

सेवाएं

हम भी व्यंजनों एपीआई की जरूरत है। redux-saga का उपयोग करते समय सेवा घोषित करने का सबसे आसान तरीका एक (शुद्ध) फ़ंक्शन बनाना है जो अनुरोध को तर्क के रूप में पढ़ता है और Promise देता है।

// api.js 
const url = "https://YOUR_ENPOINT"; 

export function fetchRecipes(request) { 
    return fetch(url).then(response => response.json()) 
} 

अब हमें कार्यों और सेवाओं को तार करने की आवश्यकता है। यह वह जगह है जहां redux-saga खेल में आते हैं।

// saga.js 
import {call, fork, put, take} from "redux-saga/effects" 
import * as actions from "./actions" 
import * as api from "./api" 

function* watchFetchRecipes() { 
    while (true) { 
    // Wait for `RECIPES.REQUEST` actions and extract the `request` payload 
    const {request} = yield take(actions.RECIPES.REQUEST) 

    try { 
     // Fetch the recipes 
     const recipes = yield call(api.fetchRecipes(request)) 

     // Send a new action to notify the UI 
     yield put(actions.fetchRecipes.success(recipes)) 
    } catch (e) { 
     // Notify the UI that something went wrong 
     yield put(actions.fetchRecipes.error(e)) 
    } 
    } 
} 

function* rootSaga() { 
    yield [ 
    fork(watchFetchRecipes) 
    ] 
} 

और यही वह है! जब भी कोई घटक RECIPES.REQUEST क्रिया भेजता है, तो गाथा एसिंक वर्कफ़्लो को हुक अप और संभाल लेगी।

dispatch(recipes.request(req)) 

क्या redux-saga साथ ही कमाल का है कि आप आसानी से कार्यप्रवाह दौरान async प्रभाव और प्रेषण कार्रवाई श्रृंखला कर सकते हैं।

+1

मैं यहां टिप्पणी कर रहा हूं क्योंकि मुझे फिर से परामर्श करने की आवश्यकता है और आपकी व्याख्या शानदार हो रही है। –

1

आपके विवरण के आधार पर, आप वास्तव में अपना यूआई अपडेट करते समय केवल इन सभी एसिंक्रोनस ऑपरेशंस (बी 1) के अंत में सही हैं।

यदि आप अपने आवेदन स्थिति को बदलने/अपने यूआई को अपडेट करने के लिए पिछले एसिंक कॉल से परिणामों का उपयोग नहीं करते हैं, तो इन बढ़िया कार्यवाही करने का क्या फायदा है?

बेशक ऐसी चीजें हैं जैसे "लोडिंग/अनुरोध शुरू हुआ" और "समाप्त लोडिंग/अनुरोध बंद हो गया", लेकिन ऐसा लगता है कि आपके मामले में, आप केवल रेडक्स के बाहर जंजीर एसिंक कॉल कर सकते हैं (कुछ में एपीआई-परत की तरह) और केवल एक क्रिया का उपयोग करें। यह क्रिया एक "REQUEST_STARTED" प्रेषित करती है, फिर एपीआई-लेयर को कॉल करती है, जो डीबी-कॉल और लोचदार अनुरोध अनुरोध इत्यादि करती है, और फिर वादे के परिणाम के आधार पर या तो "REQUEST_SUCCESS" या "REQUEST_FAILURE" प्रेषित करती है, जो आपको अपना यूआई अपडेट करने के लिए आवश्यक डेटा दें।

इस तरह, रेडक्स में राज्य केवल आपकी साइड कॉल के कार्यान्वयन विवरण के बजाय एक तरफ प्रभाव से संबंधित है। साथ ही, आपकी कार्रवाई बहुत आसान हो जाती है, क्योंकि यह सिर्फ एक async कॉल के परिणामों को संभालती है।