ES6 जनरेटर के साथ redux-thunk के साथ redux-saga का उपयोग करने के पेशेवरों / विपक्ष


488

अभी Redux शहर में नवीनतम बच्चे के बारे में बहुत चर्चा है, redux-saga / redux-saga । यह सुनने / प्रेषण क्रियाओं के लिए जनरेटर कार्यों का उपयोग करता है।

इससे पहले कि मैं अपना सिर इसके चारों ओर लपेटूं, मैं redux-sagaनीचे दिए गए दृष्टिकोण के बजाय उपयोग करने के पेशेवरों / विपक्षों को जानना चाहूंगा जहां मैं redux-thunkasync या प्रतीक्षा के साथ उपयोग कर रहा हूं ।

एक घटक इस तरह दिख सकता है, सामान्य रूप से कार्रवाई भेज सकता है।

import { login } from 'redux/auth';

class LoginForm extends Component {

  onClick(e) {
    e.preventDefault();
    const { user, pass } = this.refs;
    this.props.dispatch(login(user.value, pass.value));
  }

  render() {
    return (<div>
        <input type="text" ref="user" />
        <input type="password" ref="pass" />
        <button onClick={::this.onClick}>Sign In</button>
    </div>);
  } 
}

export default connect((state) => ({}))(LoginForm);

तब मेरी हरकतें कुछ इस तरह दिखती हैं:

// auth.js

import request from 'axios';
import { loadUserData } from './user';

// define constants
// define initial state
// export default reducer

export const login = (user, pass) => async (dispatch) => {
    try {
        dispatch({ type: LOGIN_REQUEST });
        let { data } = await request.post('/login', { user, pass });
        await dispatch(loadUserData(data.uid));
        dispatch({ type: LOGIN_SUCCESS, data });
    } catch(error) {
        dispatch({ type: LOGIN_ERROR, error });
    }
}

// more actions...

// user.js

import request from 'axios';

// define constants
// define initial state
// export default reducer

export const loadUserData = (uid) => async (dispatch) => {
    try {
        dispatch({ type: USERDATA_REQUEST });
        let { data } = await request.get(`/users/${uid}`);
        dispatch({ type: USERDATA_SUCCESS, data });
    } catch(error) {
        dispatch({ type: USERDATA_ERROR, error });
    }
}

// more actions...

6
मेरे जवाब को भी देखिए, redux-thunk की तुलना redux-saga से करने के लिए यहाँ: stackoverflow.com/a/34623840/82609
सेबस्टियन लॉर्बर

22
::आपके this.onClickकरने से पहले क्या है ?
डाउनहिल्स्की

37
@ZhenyangHua यह ऑब्जेक्ट ( this), उर्फ ​​के लिए फ़ंक्शन को बाँधने के लिए एक छोटा हाथ है this.onClick = this.onClick.bind(this)। लंबे समय तक फॉर्म को आमतौर पर कंस्ट्रक्टर में करने की सिफारिश की जाती है, क्योंकि हर रेंडर पर शॉर्ट हैंड रि-बाइंड होते हैं।
हैम्पसोहेल्सन

7
समझा। धन्यवाद! मैं देख रहा हूँ कि लोग फंक्शन bind()को पास thisकरने के लिए बहुत प्रयोग कर रहे () => method()हैं , लेकिन मैंने अब उपयोग करना शुरू कर दिया है ।
डाउनहिल्स्की

2
@ होसर मैं थोड़ी देर के लिए उत्पादन में redux और redux-saga का उपयोग करता था, लेकिन वास्तव में कुछ महीनों के बाद MobX में स्थानांतरित हो गया क्योंकि कम ओवरहेड
hampusohlsson

जवाबों:


461

Redux-saga में, उपरोक्त उदाहरण के बराबर होगा

export function* loginSaga() {
  while(true) {
    const { user, pass } = yield take(LOGIN_REQUEST)
    try {
      let { data } = yield call(request.post, '/login', { user, pass });
      yield fork(loadUserData, data.uid);
      yield put({ type: LOGIN_SUCCESS, data });
    } catch(error) {
      yield put({ type: LOGIN_ERROR, error });
    }  
  }
}

export function* loadUserData(uid) {
  try {
    yield put({ type: USERDATA_REQUEST });
    let { data } = yield call(request.get, `/users/${uid}`);
    yield put({ type: USERDATA_SUCCESS, data });
  } catch(error) {
    yield put({ type: USERDATA_ERROR, error });
  }
}

ध्यान देने वाली पहली बात यह है कि हम फॉर्म का उपयोग करके एपीआई कार्यों को बुला रहे हैं yield call(func, ...args)callप्रभाव को निष्पादित नहीं करता है, यह सिर्फ एक सादे वस्तु की तरह बनाता है {type: 'CALL', func, args}। निष्पादन को Redux-saga मिडलवेयर को सौंपा जाता है जो फ़ंक्शन को निष्पादित करने और इसके परिणाम के साथ जनरेटर को फिर से शुरू करने का ख्याल रखता है।

मुख्य लाभ यह है कि आप साधारण समानता की जांच का उपयोग करके Redux के बाहर जनरेटर का परीक्षण कर सकते हैं

const iterator = loginSaga()

assert.deepEqual(iterator.next().value, take(LOGIN_REQUEST))

// resume the generator with some dummy action
const mockAction = {user: '...', pass: '...'}
assert.deepEqual(
  iterator.next(mockAction).value, 
  call(request.post, '/login', mockAction)
)

// simulate an error result
const mockError = 'invalid user/password'
assert.deepEqual(
  iterator.throw(mockError).value, 
  put({ type: LOGIN_ERROR, error: mockError })
)

ध्यान दें कि हम एपिक कॉल रिजल्ट का मजाक उड़ा रहे हैं next। मॉकिंग डेटा मॉकिंग फ़ंक्शन की तुलना में अधिक सरल है।

नोटिस करने के लिए दूसरी चीज कॉल है yield take(ACTION)। प्रत्येक नई क्रिया (जैसे LOGIN_REQUEST) पर एक्शन क्रिएटर द्वारा थ्रक्स को बुलाया जाता है । यानी क्रियाओं लगातार कर रहे हैं धक्का दिया Thunks के लिए, और Thunks जब उन कार्यों से निपटने को रोकने के लिए पर कोई नियंत्रण नहीं।

Redux-saga में, जनरेटर अगली कार्रवाई को खींचते हैं । यानी कुछ कार्रवाई के लिए सुनने के लिए उनका नियंत्रण है, और कब नहीं। उपरोक्त उदाहरण में प्रवाह निर्देश एक while(true)लूप के अंदर रखे गए हैं , इसलिए यह प्रत्येक आने वाली कार्रवाई के लिए सुनेंगे, जो कुछ हद तक ठग को व्यवहार की नकल करता है।

पुल दृष्टिकोण जटिल नियंत्रण प्रवाह को लागू करने की अनुमति देता है। उदाहरण के लिए मान लें कि हम निम्नलिखित आवश्यकताओं को जोड़ना चाहते हैं

  • उपयोगकर्ता कार्रवाई को संभालना

  • पहले सफल लॉगिन पर, सर्वर एक टोकन देता है जो किसी expires_inफ़ील्ड में संग्रहीत कुछ देरी में समाप्त हो जाता है । हमें प्रत्येक expires_inमिलीसेकंड पर पृष्ठभूमि में प्राधिकरण को ताज़ा करना होगा

  • इस बात का ध्यान रखें कि जब आपी कॉल (प्रारंभिक लॉगिन या रिफ्रेश) के परिणाम का इंतजार कर रहे हों, तो उपयोगकर्ता बीच-बीच में लॉगआउट कर सकता है।

आप इसे कैसे लागू करेंगे? संपूर्ण प्रवाह के लिए पूर्ण परीक्षण कवरेज प्रदान करते हुए भी? यहां बताया गया है कि यह कैसे लग सकता है:

function* authorize(credentials) {
  const token = yield call(api.authorize, credentials)
  yield put( login.success(token) )
  return token
}

function* authAndRefreshTokenOnExpiry(name, password) {
  let token = yield call(authorize, {name, password})
  while(true) {
    yield call(delay, token.expires_in)
    token = yield call(authorize, {token})
  }
}

function* watchAuth() {
  while(true) {
    try {
      const {name, password} = yield take(LOGIN_REQUEST)

      yield race([
        take(LOGOUT),
        call(authAndRefreshTokenOnExpiry, name, password)
      ])

      // user logged out, next while iteration will wait for the
      // next LOGIN_REQUEST action

    } catch(error) {
      yield put( login.error(error) )
    }
  }
}

उपरोक्त उदाहरण में, हम अपनी संगणकीय आवश्यकता का उपयोग करके व्यक्त कर रहे हैं race। यदि take(LOGOUT)रेस जीतता है (यानी उपयोगकर्ता एक लॉगआउट बटन पर क्लिक करता है)। दौड़ स्वचालित रूप से authAndRefreshTokenOnExpiryपृष्ठभूमि कार्य को रद्द कर देगी । और अगर कॉल के authAndRefreshTokenOnExpiryबीच में ब्लॉक किया गया था call(authorize, {token})तो उसे भी रद्द कर दिया जाएगा। रद्दीकरण स्वचालित रूप से नीचे की ओर फैलता है।

आप उपरोक्त प्रवाह का एक रनवेबल डेमो पा सकते हैं


@yassine delayसमारोह कहाँ से आ रहा है? आह, पाया गया: github.com/yelouafi/redux-saga/blob/…
philk

122
redux-thunk-समझाया स्वयं कोड काफी पठनीय और है। लेकिन redux-sagas: एक मुख्य रूप से उन लोगों के क्रिया-जैसे कार्यों की वजह से वास्तव में पढ़ने योग्य नहीं है, call, fork, take, put...
syg

11
@ ओएसजी, मैं मानता हूं कि कॉल, कांटा, लेना और डाल देना अधिक शब्दार्थ के अनुकूल हो सकता है। हालाँकि, यह उन क्रिया-समान कार्य हैं जो सभी दुष्प्रभावों को परीक्षण योग्य बनाते हैं।
डाउनहिल्स्की

3
@syg अभी भी उन अजीब क्रियाओं के साथ एक फ़ंक्शन है जो कि अधिक वादों से अधिक पठनीय है, जिसमें गहरी वादों की श्रृंखला है
यासर सिनजाब

3
उन "अजीब" क्रियाओं की मदद से आप गाथा के रिश्ते को फिर से तैयार करने में मदद करते हैं। आप संदेश के प्रकारों को Redux से निकाल सकते हैं - अक्सर अगली पुनरावृत्ति को ट्रिगर करने के लिए, और आप अपने साइड इफेक्ट के परिणाम को प्रसारित करने के लिए नए संदेश वापस रख सकते हैं ।
वर्कट

104

मैं पुस्तकालय लेखक के बजाय पूरी तरह से जवाब के अलावा उत्पादन प्रणाली में गाथा का उपयोग करके अपने अनुभव को जोड़ूंगा।

प्रो (गाथा का उपयोग करके):

  • Testability। सागा को कॉल () शुद्ध वस्तु के रूप में जांचना बहुत आसान है। सामान्य रूप से परीक्षण थ्रक्स आपको अपने परीक्षण के अंदर मॉकस्टोर शामिल करने की आवश्यकता होती है।

  • Redux-saga कार्यों के बारे में बहुत उपयोगी सहायक कार्यों के साथ आता है। मुझे यह प्रतीत होता है कि गाथा की अवधारणा आपके ऐप के लिए किसी प्रकार के बैकग्राउंड वर्कर / थ्रेड का निर्माण करना है, जो कि रिड्यूस आर्किटेक्चर (एक्शन क्रिएटर्स और रिड्यूसर्स के शुद्ध कार्य होने चाहिए) में एक लापता कृति के रूप में कार्य करता है। जो अगले बिंदु पर ले जाता है।

  • सभी साइड इफेक्ट्स को संभालने के लिए सागर स्वतंत्र स्थान प्रदान करते हैं। आमतौर पर मेरे अनुभव में थंक कार्यों की तुलना में इसे संशोधित करना और प्रबंधित करना आसान है।

कोन:

  • जेनरेटर सिंटैक्स।

  • सीखने के लिए बहुत सारी अवधारणाएँ।

  • एपीआई स्थिरता। ऐसा लगता है कि Redux-saga अभी भी सुविधाएँ जोड़ रहा है (जैसे चैनल?) और समुदाय उतना बड़ा नहीं है। पुस्तकालय में किसी दिन गैर-पिछड़े संगत अद्यतन करने पर चिंता होती है।


9
बस कुछ टिप्पणी करना चाहते हैं, एक्शन क्रिएटर को शुद्ध कार्य करने की आवश्यकता नहीं है, जो कई बार खुद दान द्वारा दावा किया गया है।
मार्सन माओ

14
अब तक, Redux-sagas को उपयोग करने की बहुत सिफारिश की जाती है और समुदाय का विस्तार हुआ है। इसके अलावा, एपीआई और अधिक परिपक्व हो गया है। API stabilityवर्तमान स्थिति को प्रतिबिंबित करने के लिए अपडेट के रूप में कोन को हटाने पर विचार करें ।
डेनियलोस

1
गाथा की शुरुआत
थन

2
हाँ, FWIW redux-saga में अब 12k तारे हैं, Redux-thunk में 8k है
ब्रायन बर्न्स

3
मैं सगाओं की एक और चुनौती जोड़ने जा रहा हूं, यह है कि सगाओं को डिफ़ॉल्ट रूप से एक्शन और एक्शन क्रिएटर्स से पूरी तरह से अलग कर दिया जाता है। थ्रोक्स सीधे एक्शन क्रिएटर्स को अपने साइड इफेक्ट्स से जोड़ते हैं, लेकिन सागा एक्शन क्रिएटर्स को उनके लिए सुनने वाले सागों से पूरी तरह से अलग कर देता है। इसके तकनीकी फायदे हैं, लेकिन कोड का पालन करना अधिक कठिन बना सकता है, और कुछ अप्रत्यक्ष अवधारणाओं को धुंधला कर सकता है।
थिसोफॉस्फेटड

33

मैं अपने व्यक्तिगत अनुभव (साग और ठग दोनों का उपयोग करके) से कुछ टिप्पणियां जोड़ना चाहूंगा:

सागा परीक्षण करने के लिए महान हैं:

  • आप प्रभाव के साथ लिपटे कार्यों का मजाक उड़ाने की जरूरत नहीं है
  • इसलिए परीक्षण साफ, पठनीय और लिखने में आसान हैं
  • सागों का उपयोग करते समय, एक्शन क्रिएटर्स ज्यादातर सादे वस्तु शाब्दिक वापस करते हैं। थंक के वादों के विपरीत परीक्षण करना और मुखर करना भी आसान है।

सगा अधिक शक्तिशाली हैं। एक थंक के एक्शन क्रिएटर में आप जो कर सकते हैं, वह सब आप एक गाथा में भी कर सकते हैं, लेकिन इसके विपरीत (या कम से कम आसानी से नहीं)। उदाहरण के लिए:

  • एक कार्रवाई / कार्रवाई के लिए भेजे जाने की प्रतीक्षा करें ( take)
  • मौजूदा दिनचर्या रद्द ( cancel, takeLatest, race)
  • कई दिनचर्या ही कार्रवाई को सुन सकते हैं ( take, takeEvery, ...)

सगा अन्य उपयोगी कार्यक्षमता भी प्रदान करता है, जो कुछ सामान्य एप्लिकेशन पैटर्न को सामान्य करता है:

  • channels बाहरी ईवेंट स्रोतों (जैसे वेबस्कैट) पर सुनने के लिए
  • कांटा मॉडल ( fork, spawn)
  • गला घोंटना
  • ...

साग महान और शक्तिशाली उपकरण हैं। हालाँकि शक्ति के साथ जिम्मेदारी आती है। जब आपका आवेदन बढ़ता है, तो आप यह पता लगाकर आसानी से खो सकते हैं कि कौन कार्यवाही के लिए प्रतीक्षा कर रहा है, या जब कुछ कार्रवाई प्रेषित की जा रही है तो सब कुछ क्या होगा। दूसरी ओर ठग सरल और आसान है। एक या दूसरे को चुनना परियोजना के प्रकार और आकार जैसे कई पहलुओं पर निर्भर करता है कि आपकी परियोजना को किस प्रकार के दुष्प्रभाव को संभालना चाहिए या टीम की प्राथमिकता को पूरा करना चाहिए। किसी भी मामले में बस अपने आवेदन को सरल और अनुमानित रखें।


8

बस कुछ व्यक्तिगत अनुभव:

  1. कोडिंग शैली और पठनीयता के लिए, अतीत में redux-saga का उपयोग करने के सबसे महत्वपूर्ण लाभों में से एक redux-thunk में कॉलबैक नरक से बचने के लिए है - किसी को कई घोंसले का उपयोग करने की आवश्यकता नहीं है / फिर अब पकड़ लें। लेकिन अब async / वेट थंक की लोकप्रियता के साथ, कोई भी सिंक-शैली में async कोड लिख सकता है जब redux-thunk का उपयोग किया जाता है, जिसे redux-think में सुधार माना जा सकता है।

  2. Redux-saga का उपयोग करते समय किसी को अधिक बॉयलरप्लेट कोड लिखने की आवश्यकता हो सकती है, विशेष रूप से टाइपस्क्रिप्ट में। उदाहरण के लिए, यदि कोई एक भ्रूण async फ़ंक्शन को लागू करना चाहता है, तो डेटा और त्रुटि हैंडलिंग सीधे कार्रवाई में एक thunk इकाई में किया जा सकता है। एक एकल FETCH कार्रवाई के साथ। लेकिन Redux-saga में, किसी को FETCH_START, FETCH_SUCCESS और FETCH_FAILURE कार्यों और उनके सभी संबंधित प्रकार की जाँच को परिभाषित करने की आवश्यकता हो सकती है, क्योंकि Redux-saga में सुविधाओं में से एक इस तरह के समृद्ध "टोकन" तंत्र का उपयोग करना है ताकि वे प्रभाव पैदा कर सकें और निर्देश दे सकें। आसान परीक्षण के लिए redux स्टोर। बेशक कोई भी इन कार्यों का उपयोग किए बिना एक गाथा लिख ​​सकता है, लेकिन यह एक ठग के समान होगा।

  3. फ़ाइल संरचना के संदर्भ में, Redux-saga कई मामलों में अधिक स्पष्ट प्रतीत होता है। हर sagas.ts में एक आसानी से एक async संबंधित कोड मिल सकता है, लेकिन redux-thunk में, किसी को इसे कार्यों में देखने की आवश्यकता होगी।

  4. Redux-saga में आसान परीक्षण एक और भारित सुविधा हो सकती है। यह वास्तव में सुविधाजनक है। लेकिन एक बात जिसे स्पष्ट करने की आवश्यकता है, वह यह है कि Redux-saga "call" परीक्षण परीक्षण में वास्तविक API कॉल नहीं करेगा, इस प्रकार किसी व्यक्ति को उन चरणों के लिए नमूना परिणाम निर्दिष्ट करने की आवश्यकता होगी जो API कॉल के बाद इसका उपयोग कर सकते हैं। इसलिए redux-saga में लिखने से पहले, एक गाथा और उसके संबंधित sagas.spec.ts के बारे में विस्तार से योजना बनाना बेहतर होगा।

  5. Redux-saga कई उन्नत सुविधाएँ भी प्रदान करता है जैसे कि समांतर में रनिंग कार्य, लिकरेस्ट / टेक एवरी, फोर्क / स्पॉन जैसे कंसीलर हेल्पर्स, जो थ्रक्स की तुलना में कहीं अधिक शक्तिशाली हैं।

अंत में, व्यक्तिगत रूप से, मैं कहना चाहूंगा: कई सामान्य मामलों में और छोटे से मध्यम आकार के ऐप्स के लिए, async / प्रतीक्षा शैली redux-thunk के साथ जाएं। यह आपको कई बॉयलरप्लेट कोड / एक्शन / टाइपडेफ़्स को बचाएगा, और आपको कई अलग-अलग sagas.ts के चारों ओर स्विच करने और एक विशिष्ट सागा पेड़ बनाए रखने की आवश्यकता नहीं होगी। लेकिन अगर आप एक बड़े ऐप को विकसित कर रहे हैं जिसमें बहुत ही जटिल एस्कॉइन लॉजिक है और कंसीडर / पैरलल पैटर्न जैसे फीचर्स की जरूरत है, या टेस्टिंग और मेंटेनेंस की खासी डिमांड है (खासतौर पर टेस्ट-संचालित डेवलपमेंट में), तो redux-sagas संभवतः आपकी जिंदगी बचाएगी ।

वैसे भी, Redux-saga, Redux की तुलना में अधिक कठिन और जटिल नहीं है, और इसमें एक तथाकथित खड़ी सीखने की अवस्था नहीं है क्योंकि इसमें अच्छी तरह से सीमित अवधारणाएं और एपीआई हैं। Redux-saga सीखने में बहुत कम समय खर्च करने से भविष्य में एक दिन खुद को फायदा हो सकता है।


5

मेरे अनुभव में कुछ अलग-अलग बड़े पैमाने पर रिएक्ट / रिडक्स प्रोजेक्ट्स की समीक्षा करने के बाद, सागा डेवलपर्स को कोड लिखने का एक अधिक संरचित तरीका प्रदान करता है जो परीक्षण करने के लिए बहुत आसान है और गलत होने के लिए कठिन है।

हाँ, इसे शुरू करने में थोड़ा अशिष्ट है, लेकिन अधिकांश देवों को एक दिन में इसकी समझ हो जाती है। मैं हमेशा लोगों को बताता हूं कि किस चीज की चिंता नहीं करनी चाहिएyield कि इसके साथ शुरू करना है और एक बार जब आप एक दो परीक्षण लिखेंगे तो यह आपके पास आ जाएगा।

मैंने कुछ परियोजनाओं को देखा है जहां थ्रक्स का इलाज किया गया है जैसे कि वे एमवीसी पेटेंट से नियंत्रक हैं और यह जल्दी से एक अस्वस्थ गड़बड़ हो जाता है।

मेरी सलाह है कि आप ऐसे साग का उपयोग करें जहां आपको किसी एक घटना से संबंधित ए प्रकार बी सामान की आवश्यकता हो। ऐसी कई चीज़ों के लिए, जो कई कार्रवाइयों में कटौती कर सकती हैं, मुझे लगता है कि ग्राहक को मिडलवेयर लिखना आसान है और इसे ट्रिगर करने के लिए एफएसए कार्रवाई की मेटा प्रॉपर्टी का उपयोग करें।


2

थ्रो बनाम सागा

Redux-Thunkऔर Redux-Sagaकुछ महत्वपूर्ण तरीकों से अलग, दोनों Redux के लिए मिडलवेयर लाइब्रेरी हैं (Redux मिडलवेयर कोड है जो डिस्पैच () विधि) के माध्यम से स्टोर में आने वाली क्रियाओं को स्वीकार करता है।

एक क्रिया वस्तुतः कुछ भी हो सकती है, लेकिन यदि आप सर्वोत्तम प्रथाओं का पालन कर रहे हैं, तो एक क्रिया एक प्रकार की फ़ील्ड, और वैकल्पिक पेलोड, मेटा और त्रुटि फ़ील्ड के साथ एक सादे जावास्क्रिप्ट ऑब्जेक्ट है। जैसे

const loginRequest = {
    type: 'LOGIN_REQUEST',
    payload: {
        name: 'admin',
        password: '123',
    }, };

Redux-thunk

प्रेषण मानक कार्यों के अलावा, Redux-Thunkमिडलवेयर आपको विशेष कार्यों को भेजने की अनुमति देता है, जिन्हें कहा जाता हैthunks

थ्रो (Redux में) में आमतौर पर निम्नलिखित संरचना होती है:

export const thunkName =
   parameters =>
        (dispatch, getState) => {
            // Your application logic goes here
        };

यही है, एक thunkऐसा फ़ंक्शन है जो (वैकल्पिक रूप से) कुछ मापदंडों को लेता है और एक अन्य फ़ंक्शन देता है। आंतरिक फ़ंक्शन एक dispatch functionऔर एक फ़ंक्शन लेता है getState- दोनों की आपूर्ति Redux-Thunkमिडलवेयर द्वारा की जाएगी ।

Redux-सागा

Redux-Sagaमिडलवेयर आपको जटिल एप्लिकेशन लॉजिक को शुद्ध कार्यों के रूप में व्यक्त करने की अनुमति देता है जिसे सागा कहा जाता है। शुद्ध कार्य परीक्षण के दृष्टिकोण से वांछनीय हैं क्योंकि वे पूर्वानुमान योग्य और दोहराए जाने वाले हैं, जो उन्हें परीक्षण करने में अपेक्षाकृत आसान बनाता है।

सगा को विशेष कार्यों के माध्यम से कार्यान्वित किया जाता है जिसे जनरेटर फ़ंक्शन कहा जाता है। ये एक नई सुविधा है ES6 JavaScript। मूल रूप से, निष्पादन एक जनरेटर के अंदर और बाहर कूदता है हर जगह आप एक उपज बयान देखते हैं। yieldजेनरेटर को रोकने और उपज के मूल्य को वापस करने के लिए एक बयान के बारे में सोचें । बाद में, कॉल करने वाले बयान पर जनरेटर को फिर से शुरू कर सकता हैyield

एक जनरेटर फ़ंक्शन इस तरह से परिभाषित किया गया है। फ़ंक्शन कीवर्ड के बाद तारांकन चिह्न देखें।

function* mySaga() {
    // ...
}

एक बार लॉगिन गाथा के साथ पंजीकृत है Redux-Saga। लेकिन तब yieldपहली पंक्ति पर ले जाना गाथा को तब तक रोक देगा जब तक 'LOGIN_REQUEST'कि स्टोर के साथ एक प्रकार की कार्रवाई नहीं की जाती है। एक बार ऐसा होने पर, निष्पादन जारी रहेगा।

अधिक जानकारी के लिए इस लेख को देखें


1

एक त्वरित नोट। जेनरेटर रद्द करने योग्य हैं, async / प्रतीक्षा - नहीं। तो सवाल से एक उदाहरण के लिए, यह वास्तव में समझ में नहीं आता है कि क्या चुनना है। लेकिन अधिक जटिल प्रवाह के लिए कभी-कभी जनरेटर का उपयोग करने से बेहतर कोई उपाय नहीं है।

इसलिए, एक और विचार रेडिएटर-थंक के साथ जनरेटर का उपयोग करना हो सकता है, लेकिन मेरे लिए, यह ऐसा लगता है जैसे कि स्क्वायर पहियों के साथ एक साइकिल का आविष्कार करने की कोशिश कर रहा है।

और हां, जनरेटर परीक्षण करने में आसान हैं।


0

यहां एक परियोजना है जो दोनों के सर्वोत्तम भागों (पेशेवरों) को जोड़ती है : redux-sagaऔर redux-thunkआप dispatchingइसी क्रिया द्वारा एक वादा प्राप्त करते समय सागा पर सभी दुष्प्रभावों को संभाल सकते हैं : https://github.com/diegohaz/redux-saga-thunk

class MyComponent extends React.Component {
  componentWillMount() {
    // `doSomething` dispatches an action which is handled by some saga
    this.props.doSomething().then((detail) => {
      console.log('Yaay!', detail)
    }).catch((error) => {
      console.log('Oops!', error)
    })
  }
}

1
then()रिएक्ट घटक के अंदर उपयोग करना प्रतिमान के खिलाफ है। आपको componentDidUpdateहल किए जाने वाले वादे की प्रतीक्षा करने के बजाय बदले हुए राज्य को संभालना चाहिए ।

3
@ Maxincredible52 यह सर्वर साइड रेंडरिंग के लिए सही नहीं है।
डिएगो हज

मेरे अनुभव में, सर्वर साइड रेंडरिंग के लिए मैक्स की बात अभी भी सही है। इसे शायद रूटिंग लेयर में ही संभाला जाना चाहिए।
सोच रहा

3
@ Maxincredible52 यह प्रतिमान के खिलाफ क्यों है, आपने इसे कहां पढ़ा है? मैं आमतौर पर @ डीजीओ हज के समान ही करता हूं, लेकिन इसे कंपोनेंटमाउंट में करते हैं (जैसा कि रिएक्ट डॉक्स के अनुसार, नेटवर्क कॉल बेहतर होना चाहिए)componentDidlMount() { this.props.doSomething().then((detail) => { this.setState({isReady: true})} }
user3711421

0

एक आसान तरीका Redux- ऑटो का उपयोग करना है ।

डोक्यूमेन्टेशन से

redux-auto ने इस असिंक्रोनस समस्या को केवल एक "एक्शन" फंक्शन बनाने की अनुमति देकर तय किया जो एक वादा लौटाता है। अपने "डिफ़ॉल्ट" फ़ंक्शन एक्शन लॉजिक के साथ।

  1. अन्य Redux async मिडिलवेयर की कोई आवश्यकता नहीं है। उदाहरण के लिए थन, वादा-मिडलवेयर, गाथा
  2. आसानी से आप Redux में एक वादा पारित करने की अनुमति देता है और यह आपके लिए प्रबंधित है
  3. आपको बाहरी सेवा कॉल का सह-पता लगाने की अनुमति देता है जहां वे परिवर्तित हो जाएंगे
  4. "Init.js" फ़ाइल का नामकरण ऐप शुरू होने पर एक बार कॉल करेगा। यह शुरू में सर्वर से डेटा लोड करने के लिए अच्छा है

विचार एक विशिष्ट फ़ाइल में प्रत्येक क्रिया है । फ़ाइल में "लंबित", "पूर्ण" और "अस्वीकृत" के लिए सर्वर कॉल को सह-पता लगाना। इससे हैंडलिंग के वादे बहुत आसान हो जाते हैं।

यह आपके राज्य के प्रोटोटाइप के लिए स्वचालित रूप से एक सहायक वस्तु (जिसे "async" भी कहा जाता है) को आपके यूआई, अनुरोधित बदलावों में ट्रैक करने की अनुमति देता है।


2
मैंने +1 किया यहां तक ​​कि यह अप्रासंगिक उत्तर है क्योंकि अलग-अलग समाधानों पर भी विचार किया जाना चाहिए
एमोरेन्यू

12
मुझे लगता है कि वे वहां हैं क्योंकि उन्होंने खुलासा नहीं किया कि वह परियोजना के लेखक हैं
jreptak
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.