37

के साथ बेहतर असीमित नियंत्रण प्रवाह मैं वेब सेवा पर असीमित कॉल के लिए AFNetworking का उपयोग कर रहा हूं। इनमें से कुछ कॉलों को एक साथ जंजीर किया जाना चाहिए, जहां कॉल ए के परिणाम कॉल बी द्वारा उपयोग किए जाते हैं, जिन्हें कॉल सी, आदि द्वारा उपयोग किया जाता है।उद्देश्य-सी ब्लॉक

AFNetworking ऑपरेशन के समय सेट/सफलता विफलता ब्लॉक के साथ एसिंक कॉल का परिणाम संभालता है बनाया गया है:

NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { 
    NSLog(@"Public Timeline: %@", JSON); 
} failure:nil]; 
[operation start]; 

इसका परिणाम नेस्टेड एसिंक कॉल ब्लॉक में होता है जो जल्दी से अपठनीय हो जाता है। यह तब भी जटिल होता है जब कार्य एक दूसरे पर निर्भर नहीं होते हैं और इसके बजाय समानांतर और निष्पादन में निष्पादित होना चाहिए सभी परिचालनों के परिणामों पर निर्भर करता है।

ऐसा लगता है कि नियंत्रण प्रवाह को साफ करने के लिए promises ढांचे का लाभ उठाने का एक बेहतर तरीका होगा।

मैं MAFuture पर आया हूं लेकिन यह पता नहीं लगा सकता कि AFNetworking के साथ इसे कैसे एकीकृत किया जाए। चूंकि एसिंक कॉल में कई परिणाम हो सकते हैं (सफलता/विफलता) और वापसी मूल्य नहीं है, यह आदर्श फिट जैसा प्रतीत नहीं होता है।

किसी भी पॉइंटर्स या विचारों की सराहना की जाएगी।

+0

इस प्रश्न के लिए धन्यवाद - आपके पास कुछ शानदार जवाब हैं।हालांकि शुरुआत में मुझे थोड़ी परेशानी हो रही थी, और यहां वादे को देखकर यहां पहुंचा। यह एंटी-पैटर्न किसी भी एसिंक्रोनस कॉलबैक एपीआई के लिए हो सकता है: यह AFNetworking विशिष्ट नहीं है। मैं एक खोज का उपयोग कर रहा था जैसे: "serialising नेस्टेड ब्लॉक कॉलबैक"। शायद कुछ और टैग मदद कर सकते हैं? यह सिर्फ मुझे हो सकता है! :-) – Benjohn

उत्तर

10

मैंने अभी तक इसका उपयोग नहीं किया है, लेकिन ऐसा लगता है कि Reactive Cocoa आपके द्वारा वर्णन किए जाने वाले कार्यों को करने के लिए डिज़ाइन किया गया था।

+1

मैंने इसका इस्तेमाल किया है, और जॉन सही है। यह वास्तव में इस तरह की चीज़ के लिए बहुत अच्छा है। –

+0

दिलचस्प। मैं प्रतिक्रियाशील कोको में आऊंगा लेकिन इस परिदृश्य के लिए इसे नहीं मानता था। चूंकि एएफ ऑपरेशंस सभी केवीओ अनुपालन हैं, इसलिए मैं संचालन कतार या व्यक्तिगत संचालन में हैंडलर जोड़ सकता हूं। मैं उसके साथ गड़बड़ करूँगा। – bromanko

+1

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

10

गौल्ला में एएफनेटवर्किंग का उपयोग करते समय यह असामान्य नहीं था कि कॉल ब्लॉक सफलतापूर्वक ब्लॉक में एक साथ बंधे हों।

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

इसके अलावा, यदि आप इसे पहले से उपयोग नहीं कर रहे हैं, तो AFHTTPClient इन प्रकार के जटिल नेटवर्क इंटरैक्शन को बहुत सरल बनाता है।

+0

धन्यवाद @mattt। यह मूल रूप से मैं अब क्या कर रहा हूं। नेस्टेड ब्लॉक में कोड गंध की भावना है। यह वही गंध है जो मुझे गहरा घोंसला सशर्त तर्क के साथ मिलता है। शायद मैं कुछ स्वच्छता के लिए उत्सुक हूं कि node.js और अन्य जावास्क्रिप्ट ढांचे और अधिक पठनीय कार्यात्मक प्रोग्रामिंग के लिए पेशकश करते हैं। – bromanko

+1

गहरा घोंसला इस दृष्टिकोण का निहित परिणाम नहीं है - प्रभावी ढंग से कॉलबैक को अपने तरीके से फैक्टर करके, इसे एक कार्यात्मक भाषा में चेनिंग की तरह बहुत अधिक दिखना चाहिए। दो घोंसले वाली कॉलों से गहराई से जाना जाने के लिए निश्चित रूप से एक गंध है, और इसका शायद यह अर्थ है कि आपको एक नई एपीआई कॉल बनाने पर विचार करना चाहिए ताकि आपको एक बार में क्या चाहिए (यदि वह आपकी शक्ति में है) – mattt

19

मैंने इसके लिए हल्के वजन का समाधान बनाया। इसे सेक्वेंसर कहा जाता है और यह github पर है।

यह चेनिंग एपीआई कॉल (या कोई अन्य एसिंक कोड) आसान और सीधा बनाता है।

यहाँ इसके साथ AFNetworking का उपयोग करने का एक उदाहरण है:

Sequencer *sequencer = [[Sequencer alloc] init]; 

[sequencer enqueueStep:^(id result, SequencerCompletion completion) { 
    NSURL *url = [NSURL URLWithString:@"https://alpha-api.app.net/stream/0/posts/stream/global"]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { 
     completion(JSON); 
    } failure:nil]; 
    [operation start]; 
}]; 

[sequencer enqueueStep:^(NSDictionary *feed, SequencerCompletion completion) { 
    NSArray *data = [feed objectForKey:@"data"]; 
    NSDictionary *lastFeedItem = [data lastObject]; 
    NSString *cononicalURL = [lastFeedItem objectForKey:@"canonical_url"]; 

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:cononicalURL]]; 
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
     completion(responseObject); 
    } failure:nil]; 
    [operation start]; 
}]; 

[sequencer enqueueStep:^(NSData *htmlData, SequencerCompletion completion) { 
    NSString *html = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding]; 
    NSLog(@"HTML Page: %@", html); 
    completion(nil); 
}]; 

[sequencer run]; 
+1

यह अच्छा है साफ, सरल समाधान। साझा करने के लिए धन्यवाद। –

+0

चरण 1 या 2 में किसी त्रुटि के मामले में ऐसा लगता है, शेष चरणों को निष्पादित नहीं किया जाएगा। – fabb

+0

@fabb मुझे विश्वास है कि यहां वांछित परिणाम है - यह निश्चित रूप से प्रभाव है जिसे मैं प्राप्त करना चाहता हूं। – Benjohn

4

वहाँ CommonJS-शैली का एक ऑब्जेक्टिव-सी कार्यान्वयन यहाँ का वादा किया Github पर है: (से लिया

https://github.com/mproberts/objc-promise

उदाहरण Readme.md)

Deferred *russell = [Deferred deferred]; 
Promise *promise = [russell promise]; 

[promise then:^(NSString *hairType){ 
    NSLog(@"The present King of France is %@!", hairType); 
}]; 

[russell resolve:@"bald"]; 

// The present King of France is bald! 

मैंने अभी तक टी नहीं किया है इस पुस्तकालय से बाहर निकला, लेकिन यह थोड़ा जबरदस्त उदाहरण के बावजूद 'आशाजनक' दिखता है। (क्षमा करें, मैं विरोध नहीं कर सका)।

+0

ऐसा लगता है कि यह बहुत उपयोगी हो सकता है लेकिन यह एआरसी अनुपालन नहीं है और मेरे पास इसे {sigh} बनाने के लिए जरूरी नहीं है। – mpemburn

+1

ऐसा लगता है कि यह एआरसी अनुपालन करता है: https://github.com/mproberts/objc-promise/commit/9bdeac0d6b1305f00c9c3e4c64bef2743536ed9a – eremzeit

6

PromiseKit उपयोगी हो सकता है। यह एक अधिक लोकप्रिय वादे कार्यान्वयन में से एक प्रतीत होता है, और अन्य ने एएफनेटवर्किंग जैसी पुस्तकालयों के साथ इसे एकीकृत करने के लिए श्रेणियां लिखी हैं, PromiseKit-AFNetworking देखें।