2013-04-03 23 views
32

प्रतिक्रियाशील कोको में, यदि हम कई निर्भर संकेतों को चेन करते हैं, तो हमें चेन में अगले सिग्नल के लिए subscribeNext: का उपयोग करना चाहिए, उदाहरण के लिए, पिछले एसिंक्रोनस ऑपरेशन का परिणाम प्राप्त करने के लिए श्रृंखला में अगले सिग्नल के लिए subscribeNext: का उपयोग करना होगा। तो कुछ समय के बाद, कोड कुछ इस तरह में बदल जाता है (अनावश्यक विवरण छोड़े गए हैं):प्रतिक्रियाशील कोको

RACSignal *buttonClickSignal = [self.logIn rac_signalForControlEvents:UIControlEventTouchUpInside]; 

[buttonClickSignal subscribeNext:^(UIButton *sender) { // signal from a button click 
    // prepare data 

    RACSignal *loginSignal = [self logInWithUsername:username password:password]; // signal from the async network operation 

    [loginSignal subscribeNext:^void (NSDictionary *json) { 
     // do stuff with data received from the first network interaction, prepare some new data 

     RACSignal *playlistFetchSignal = [self fetchPlaylistForToken:token];   // another signal from the async network operation 

     [playlistFetchSignal subscribeNext:^(NSDictionary *json) { 
      // do more stuff with the returned data 
     }]; 

     // etc 
    }]; 
}]; 

इस बढ़ती नेस्टिंग गैर प्रतिक्रियाशील उदाहरण है कि दस्तावेज में दिया जाता है की तुलना में बेहतर नहीं लगती है:

[client logInWithSuccess:^{ 
    [client loadCachedMessagesWithSuccess:^(NSArray *messages) { 
     [client fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMessages) { 
      NSLog(@"Fetched all messages."); 
     } failure:^(NSError *error) { 
      [self presentError:error]; 
     }]; 
    } failure:^(NSError *error) { 
     [self presentError:error]; 
    }]; 
} failure:^(NSError *error) { 
    [self presentError:error]; 
}]; 

क्या मुझे कुछ याद आ रही है? क्या ReactiveCocoa में निर्भर काम को चेन करने का एक बेहतर पैटर्न है?

उत्तर

47

यह तब होता है जब RACStream और RACSignal ऑपरेटर वास्तव में काम में आते हैं। अपने विशेष उदाहरण में, आप -flattenMap: उपयोग कर सकते हैं नए संकेतों में परिणाम को शामिल करने की:

[[[buttonClickSignal 
    flattenMap:^(UIButton *sender) { 
     // prepare 'username' and 'password' 
     return [self logInWithUsername:username password:password]; 
    }] 
    flattenMap:^(NSDictionary *json) { 
     // prepare 'token' 
     return [self fetchPlaylistForToken:token]; 
    }] 
    subscribeNext:^(NSDictionary *json) { 
     // do stuff with the returned playlist data 
    }]; 

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

+1

यह समाधान मेरे लिए काम करता है। मैंने एक [ब्लॉग आलेख] लिखा है (http://www.techsfo.com/blog/2013/08/managing-nested-asynchronous-callbacks-in-objective-c-using-reactive-cocoa/) जो इस दृष्टिकोण को बताता है ज्यादा जानकारी। –

+0

@ जस्टिन, क्या आप रास्ते में त्रुटि से निपटने के उचित तरीके से अधिक विस्तार से सोचेंगे? – DogpatchTech

+0

@ डोगपैचटेक आप इसके लिए '-catch:' या '-catchTo:' का उपयोग कर सकते हैं। [यह स्पष्टीकरण] देखें (http://stackoverflow.com/questions/19439636/difference-between-catch-and-subscribeerror/19439687#19439687)। –

संबंधित मुद्दे