सफलता: / विफलता: ब्लॉक बनाम पूरा: ब्लॉक


23

मैं ऑब्जेक्टिव-सी में ब्लॉक के लिए दो सामान्य पैटर्न देखता हूं। एक सफलता की एक जोड़ी है: / विफलता: ब्लॉक, दूसरा एक पूरा होने वाला है: ब्लॉक।

उदाहरण के लिए, मैं कहता हूं कि मेरे पास एक कार्य है जो किसी वस्तु को अतुल्यकालिक रूप से वापस कर देगा और वह कार्य विफल हो सकता है। पहला पैटर्न है -taskWithSuccess:(void (^)(id object))success failure:(void (^)(NSError *error))failure। दूसरा पैटर्न है-taskWithCompletion:(void (^)(id object, NSError *error))completion

सफलता असफलता:

[target taskWithSuccess:^(id object) {
    // W00t! I've got my object
} failure:^(NSError *error) {
    // Oh noes! report the failure.
}];

समापन:

[target taskWithCompletion:^(id object, NSError *error) {
    if (object) {
        // W00t! I've got my object
    } else {
        // Oh noes! report the failure.
    }
}];

पसंदीदा पैटर्न कौन सा है? ताकत और कमजोरियां क्या हैं? आप एक दूसरे पर कब इस्तेमाल करेंगे?


मुझे पूरा यकीन है कि ऑब्जेक्टिव-सी में थ्रो / कैच के साथ अपवाद हैंडलिंग है, क्या कोई कारण है जो आप उपयोग नहीं कर सकते हैं?
FrustratedWithFormsDesigner

या तो इन परमिट के लिए एस्किंस कॉल का पीछा करते हैं, जो अपवाद आपको नहीं देते हैं।
फ्रैंक शियरर

5
@FrustratedWithFormsDesigner: stackoverflow.com/a/3678556/2289 - मुहावरेदार objc प्रवाह नियंत्रण के लिए कोशिश / पकड़ का उपयोग नहीं करता है।
चींटी

1
कृपया अपने उत्तर को प्रश्न से उत्तर की ओर ले जाने पर विचार करें ... आखिरकार, यह एक उत्तर है (और आप अपने स्वयं के प्रश्नों का उत्तर दे सकते हैं)।

1
मैंने अंत में सहकर्मी के दबाव की ओर इशारा किया और अपने उत्तर को वास्तविक उत्तर में स्थानांतरित कर दिया।
जेफरी थॉमस

जवाबों:


8

समापन कॉलबैक (सफलता / विफलता जोड़ी के विपरीत) अधिक सामान्य है। यदि आपको वापसी की स्थिति से निपटने से पहले कुछ संदर्भ तैयार करने की आवश्यकता है, तो आप इसे "if (वस्तु)" खंड से ठीक पहले कर सकते हैं। सफलता / विफलता के मामले में आपको इस कोड की नकल करनी होगी। यह निश्चित रूप से कॉलबैक शब्दार्थ पर निर्भर करता है।


मूल प्रश्न पर टिप्पणी नहीं कर सकते ... अपवाद उद्देश्य-सी (अच्छी तरह से, कोको) में वैध प्रवाह नियंत्रण नहीं हैं और इस तरह का उपयोग नहीं किया जाना चाहिए। केवल गर्व से समाप्त करने के लिए थ्रोन अपवाद को पकड़ा जाना चाहिए।

हां, मैं उसे देखने में सक्षम हूं। यदि आप -task…ऑब्जेक्ट को वापस कर सकते हैं, लेकिन ऑब्जेक्ट सही स्थिति में नहीं है, तो आपको अभी भी सफलता की स्थिति में त्रुटि से निपटने की आवश्यकता होगी।
जेफरी थॉमस

हाँ, और यदि ब्लॉक इन-प्लेस नहीं है, लेकिन आपके कंट्रोलर के तर्क के रूप में पारित हो जाता है, तो आपको दो ब्लॉक टॉस करने होंगे। यह उबाऊ हो सकता है जब कॉलबैक को कई परतों से गुजरना पड़ता है। आप हमेशा इसे अलग कर सकते हैं / वापस लिख सकते हैं, हालाँकि।

मुझे समझ में नहीं आता है कि हैंडलर कैसे पूरा होता है। पूर्णता मूल रूप से कई विधियों को एक में बदल देती है - ब्लॉक परम के रूप में। इसके अलावा, क्या सामान्य का मतलब बेहतर है? MVC में आप अक्सर दृश्य नियंत्रक में डुप्लिकेट कोड के साथ-साथ चिंताओं को अलग करने के कारण एक आवश्यक बुराई है। मुझे नहीं लगता कि MVC से दूर रहने का कोई कारण है।
बून

@ बून एक कारण है कि मैं एकल हैंडलर को अधिक सामान्य होने के रूप में देखता हूं उन मामलों के लिए जहां आप कैली / हैंडलर / ब्लॉक को स्वयं निर्धारित करेंगे कि क्या कोई ऑपरेशन सफल या विफल हुआ। आंशिक सफलता के मामलों पर विचार करें जहां आपके पास संभवतः आंशिक डेटा के साथ एक ऑब्जेक्ट है और आपकी त्रुटि ऑब्जेक्ट यह दर्शाता है कि सभी डेटा वापस नहीं किया गया था। ब्लॉक डेटा की स्वयं जांच कर सकता है और यह देखने के लिए जांच कर सकता है कि क्या यह पर्याप्त है। यह बाइनरी सफलता / असफल कॉलबैक परिदृश्य के साथ संभव नहीं है।
ट्रैविस

8

मैं कहूंगा कि क्या एपीआई एक पूरा हैंडलर या सफलता / विफलता ब्लॉकों की एक जोड़ी प्रदान करता है , मुख्य रूप से व्यक्तिगत प्राथमिकता का मामला है।

दोनों दृष्टिकोणों के पक्ष और विपक्ष हैं, हालांकि केवल मामूली अंतर हैं।

इस बात पर विचार करें कि आगे के संस्करण भी हैं, उदाहरण के लिए जहां एक पूर्ण हैंडलर में अंतिम परिणाम या संभावित त्रुटि को मिलाकर केवल एक पैरामीटर हो सकता है :

typedef void (^completion_t)(id result);

- (void) taskWithCompletion:(completion_t)completionHandler;

[self taskWithCompletion:^(id result){
    if ([result isKindOfError:[NSError class]) {
        NSLog(@"Error: %@", result);
    }
    else {
        ...
    }
}]; 

इस हस्ताक्षर का उद्देश्य यह है कि एक पूरा हैंडलर अन्य एपीआई में उदारतापूर्वक उपयोग किया जा सके ।

उदाहरण के लिए श्रेणी में NSArray के लिए एक विधि है forEachApplyTask:completion:जो क्रमिक रूप से प्रत्येक वस्तु के लिए एक कार्य को आमंत्रित करती है और एक त्रुटि आईएफएफ को तोड़ती है। चूँकि यह विधि अपने आप में अतुल्यकालिक है, इसलिए इसमें एक पूरा हैंडलर भी है:

typedef void (^completion_t)(id result);
typedef void (^task_t)(id input, completion_t);
- (void) forEachApplyTask:(task_t)task completion:(completion_t);

वास्तव में, completion_tजैसा कि ऊपर बताया गया है कि सभी परिदृश्यों को संभालने के लिए पर्याप्त और पर्याप्त सामान्य है।

हालांकि, एक अतुल्यकालिक कार्य के लिए कॉल-साइट पर इसकी पूर्ण अधिसूचना को इंगित करने के लिए अन्य साधन हैं:

वादे

वादे, जिन्हें "फ्यूचर्स", "स्थगित" या "विलंबित" भी कहा जाता है, एक अतुल्यकालिक कार्य के अंतिम परिणाम का प्रतिनिधित्व करते हैं (यह भी देखें: विकी फ्यूचर्स और वादे )।

प्रारंभ में, एक वादा "लंबित" स्थिति में है। यही है, यह "मूल्य" अभी मूल्यांकन नहीं है और अभी तक उपलब्ध नहीं है।

ऑब्जेक्टिव-सी में, एक वादा एक सामान्य वस्तु होगी जो नीचे दिखाए गए अनुसार एक एसिंक्रोनस विधि से वापस आ जाएगी:

- (Promise*) doSomethingAsync;

! एक वादा की प्रारंभिक स्थिति "लंबित" है।

इस बीच, अतुल्यकालिक कार्य इसके परिणाम का मूल्यांकन करना शुरू कर देते हैं।

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

अतुल्यकालिक कार्य, जिसने वादे की वस्तु बनाई, अंततः अपने वादे को "हल" करना चाहिए। इसका मतलब है कि, चूंकि कोई कार्य सफल हो सकता है या विफल हो सकता है, यह या तो "पूरा" एक वादा करता है, यह मूल्यांकन किए गए परिणाम को पारित करता है, या यह "अस्वीकार" करता है यह वादा करता है कि इसे पारित करने में विफलता का कारण इंगित करता है।

! एक कार्य को अंततः अपने वादे को हल करना चाहिए।

जब एक प्रॉमिस हल किया गया है, तो यह बदल नहीं सकता है कि यह अब राज्य है, इसके मूल्य सहित।

! एक वादा केवल एक बार हल किया जा सकता है ।

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

एक वादा या तो करने के लिए एक तुल्यकालिक या एक अतुल्यकालिक शैली जो सुराग में लागू किया जा सकता अवरुद्ध क्रमशः गैर अवरुद्ध अर्थ विज्ञान।

एक तुल्यकालिक शैली में वादे के मूल्य को पुनः प्राप्त करने के लिए, एक कॉल-साइट एक ऐसी विधि का उपयोग करेगी जो वर्तमान धागे को ब्लॉक करेगी जब तक कि एसिंक्रोनस कार्य द्वारा हल नहीं किया गया है और अंतिम परिणाम उपलब्ध है।

एक एसिंक्रोनस शैली में, कॉल-साइट कॉलबैक या हैंडलर ब्लॉकों को पंजीकृत करेगी जो वादा किए जाने के तुरंत बाद कॉल किया जाता है।

यह पता चला कि सिंक्रोनस शैली में कई महत्वपूर्ण नुकसान हैं जो प्रभावी रूप से अतुल्यकालिक कार्यों के गुणों को पराजित करते हैं। मानक सी ++ 11 लिब में "वायदा" के वर्तमान में त्रुटिपूर्ण कार्यान्वयन के बारे में एक दिलचस्प लेख यहां पढ़ा जा सकता है: टूटे हुए वादे-सी ++ 0x वायदा

कैसे, उद्देश्य-सी में, एक कॉल-साइट परिणाम प्राप्त करेगा?

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

हालाँकि, अगले कोड स्निपेट के लिए, मैं एक विशेष पुस्तकालय के कार्यान्वयन का उपयोग करूंगा, जो GitHub RXPromise पर उपलब्ध है । मैं RXPromise का लेखक हूँ।

अन्य कार्यान्वयन में एक समान एपीआई हो सकता है, लेकिन सिंटैक्स में छोटे और संभवतः सूक्ष्म अंतर हो सकते हैं। RXPromise वादा / ए + विनिर्देशन का एक उद्देश्य-सी संस्करण है जो जावास्क्रिप्ट में वादों के मजबूत और परस्पर कार्यान्वयन के लिए एक खुले मानक को परिभाषित करता है।

नीचे सूचीबद्ध सभी वादा पुस्तकालयों में एसिंक्रोनस शैली लागू होती है।

विभिन्न कार्यान्वयनों के बीच काफी महत्वपूर्ण अंतर हैं। RXPromise आंतरिक रूप से डिस्पैच लिब का उपयोग करता है, पूरी तरह से सुरक्षित थ्रेड है, बेहद हल्का है, और रद्द करने की तरह कई अतिरिक्त उपयोगी सुविधाएं भी प्रदान करता है।

एक कॉल-साइट "पंजीकरण" संचालकों के माध्यम से अतुल्यकालिक कार्य का अंतिम परिणाम प्राप्त करती है। "वादा / ए + विनिर्देश" विधि को परिभाषित करता है then

प्रक्रिया then

RXPromise के साथ यह इस प्रकार दिखता है:

promise.then(successHandler, errorHandler);

जहाँ successHandler एक ऐसा ब्लॉक है जिसे वादा पूरा होने पर बुलाया जाता है और त्रुटिहैंडलर एक ब्लॉक होता है जिसे वादा "अस्वीकार" होने पर बुलाया जाता है।

! thenअंतिम परिणाम प्राप्त करने और एक सफलता या एक त्रुटि हैंडलर को परिभाषित करने के लिए उपयोग किया जाता है।

RXPromise में, हैंडलर ब्लॉकों में निम्नलिखित हस्ताक्षर हैं:

typedef id (^success_handler_t)(id result);
typedef id (^error_handler_t)(NSError* error);

Success_handler का एक पैरामीटर परिणाम है जो स्पष्ट रूप से अतुल्यकालिक कार्य का अंतिम परिणाम है। इसी तरह, error_handler में एक पैरामीटर त्रुटि है जो कि असिंक्रोनस कार्य द्वारा रिपोर्ट की गई त्रुटि है जब यह विफल हुआ।

दोनों ब्लॉक का रिटर्न वैल्यू है। यह वापसी मूल्य के बारे में क्या है, जल्द ही स्पष्ट हो जाएगा।

RXPromise में, thenएक संपत्ति है जो एक ब्लॉक लौटाता है। इस ब्लॉक के दो पैरामीटर हैं, सफलता हैंडलर ब्लॉक और त्रुटि हैंडलर ब्लॉक। हैंडलर को कॉल-साइट द्वारा परिभाषित किया जाना चाहिए।

! हैंडलर को कॉल-साइट द्वारा परिभाषित किया जाना चाहिए।

तो, अभिव्यक्ति promise.then(success_handler, error_handler);का संक्षिप्त रूप है

then_block_t block promise.then;
block(success_handler, error_handler);

हम और भी संक्षिप्त कोड लिख सकते हैं:

doSomethingAsync
.then(^id(id result){
    
    return @“OK”;
}, nil);

कोड पढ़ता है: "जब यह सफल हो जाता है, तब सफलता हैंडलर को निष्पादित करें " doSomethingAsync निष्पादित करें।

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

एक और महत्वपूर्ण तथ्य यह है कि संपत्ति से लौटाए गए ब्लॉक को कॉल करने thenपर एक वादा वापस आएगा:

! then(...)प्रतिज्ञा देता है

जब प्रॉपर्टी से ब्लॉक वापस किया जाता है then, तो "रिसीवर" एक नया वादा करता है, एक बच्चा वादा करता है। रिसीवर माता-पिता का वादा बन जाता है ।

RXPromise* rootPromise = asyncA();
RXPromise* childPromise = rootPromise.then(successHandler, nil);
assert(childPromise.parent == rootPromise);

इसका क्या मतलब है?

खैर, इसके कारण हम अतुल्यकालिक कार्यों को "श्रृंखला" कर सकते हैं जो प्रभावी रूप से क्रमिक रूप से निष्पादित होते हैं।

इसके अलावा, या तो हैंडलर का रिटर्न वैल्यू रिटर्न किए गए वादे का "मूल्य" बन जाएगा। इसलिए, यदि कार्य अंतिम परिणाम @ "ओके" के साथ सफल होता है, तो लौटा हुआ वादा "" ओके "" मान के साथ "हल" (जो कि "पूरा") होगा:

RXPromise* returnedPromise = asyncA().then(^id(id result){
    return @"OK";
}, nil);

...
assert([[returnedPromise get] isEqualToString:@"OK"]);

इसी तरह, जब अतुल्यकालिक कार्य विफल हो जाता है, तो लौटा हुआ वादा हल हो जाएगा (जो कि "अस्वीकृत" है) एक त्रुटि के साथ।

RXPromise* returnedPromise = asyncA().then(nil, ^id(NSError* error){
    return error;
});

...
assert([[returnedPromise get] isKindOfClass:[NSError class]]);

हैंडलर भी एक और वादा वापस कर सकता है। उदाहरण के लिए जब वह हैंडलर किसी अन्य अतुल्यकालिक कार्य को अंजाम देता है। इस तंत्र के साथ हम अतुल्यकालिक कार्यों को "चेन" कर सकते हैं:

RXPromise* returnedPromise = asyncA().then(^id(id result){
    return asyncB(result);
}, nil);

! हैंडलर ब्लॉक का रिटर्न मूल्य बच्चे के वादे का मूल्य बन जाता है।

यदि कोई बच्चा वादा नहीं करता है, तो रिटर्न वैल्यू का कोई प्रभाव नहीं पड़ता है।

एक और अधिक जटिल उदाहरण:

यहाँ, हम पर अमल asyncTaskA, asyncTaskB, asyncTaskCऔर asyncTaskD क्रमिक रूप से - और प्रत्येक अनुवर्ती कार्य इनपुट के रूप में पूर्ववर्ती कार्य का परिणाम लेता है:

asyncTaskA()
.then(^id(id result){
    return asyncTaskB(result);
}, nil)
.then(^id(id result){
    return asyncTaskC(result);
}, nil)
.then(^id(id result){
    return asyncTaskD(result);
}, nil)
.then(^id(id result){
    // handle result
    return nil;
}, nil);

इस तरह की "श्रृंखला" को "निरंतरता" भी कहा जाता है।

गलती संभालना

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

asyncTaskA()
.then(^id(id result){
    return asyncTaskB(result);
}, nil)
.then(^id(id result){
    return asyncTaskC(result);
}, nil)
.then(^id(id result){
    return asyncTaskD(result);
}, nil)
.then(^id(id result){
    // handle result
    return nil;
}, nil);
.then(nil, ^id(NSError*error) {
    NSLog(@“”Error: %@“, error);
    return nil;
});

यह अपवाद हैंडलिंग के साथ संभवतः अधिक परिचित तुल्यकालिक शैली के समान है:

try {
    id a = A();
    id b = B(a);
    id c = C(b);
    id d = D(c);
    // handle d
}
catch (NSError* error) {
    NSLog(@“”Error: %@“, error);
}

सामान्य रूप से वादे में अन्य उपयोगी विशेषताएं हैं:

उदाहरण के लिए, एक वादे के संदर्भ में, thenएक के रूप में वांछित के रूप में कई संचालकों "रजिस्टर" कर सकते हैं। RXPromise में, रजिस्टर करने वाले हैंडलर किसी भी समय और किसी भी थ्रेड से हो सकते हैं क्योंकि यह पूरी तरह से थ्रेड-सुरक्षित है।

RXPromise में कुछ अधिक उपयोगी कार्यात्मक विशेषताएं हैं, जो कि वादा / A + विनिर्देश द्वारा आवश्यक नहीं है। एक "रद्दीकरण" है।

यह पता चला कि "रद्द करना" एक अमूल्य और महत्वपूर्ण विशेषता है। उदाहरण के लिए एक कॉल-साइट एक वादे के संदर्भ में यह cancelसंदेश भेजने के लिए यह इंगित करने के लिए कि यह अब अंतिम परिणाम में कोई दिलचस्पी नहीं है।

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

RXPromise में, एक रद्द संदेश केवल एक अभिभावक से उसके बच्चों को भेजा जाएगा, लेकिन इसके विपरीत नहीं। यही है, एक "मूल" वादा सभी बच्चों के वादों को रद्द कर देगा। लेकिन एक बच्चा वादा केवल "शाखा" को रद्द कर देगा जहां वह माता-पिता है। यदि कोई वादा पहले ही हल कर लिया गया है, तो रद्द संदेश भी बच्चों को भेज दिया जाएगा।

एक अतुल्यकालिक कार्य स्वयं अपने वादे के लिए हैंडलर को पंजीकृत कर सकता है , और इस प्रकार यह पता लगा सकता है कि किसी और ने इसे कब रद्द कर दिया। यह समय से पहले एक संभवतः लंबा और महंगा कार्य करना बंद कर सकता है।

GitHub पर दिए गए ऑब्जेक्टिव-सी में वादों के कुछ अन्य कार्यान्वयन यहां दिए गए हैं:

https://github.com/Schoonology/aplus-objc
https://github.com/affablebloke/deferred-objective-c
https://github.com/bww/FutureKit
https://github.com/jkubbk/JKPromises
https://github.com/Strilanc/ObjC-CollapsingFutures
https://github.com/b52/OMPromises
https://github.com/mproberts/objc-promise
https://github.com/kassaspieter/Promise
https: // github.com/jameswomack/Promise
https://github.com/nilfs/promise-objc
https://github.com/mxcl/PromiseKit
https://github.com/apleshkov/promises-aplus
https: // github.com/KptainO/Rebelle

और मेरा अपना कार्यान्वयन: RXPromise

यह सूची पूरी होने की संभावना नहीं है!

अपनी परियोजना के लिए तीसरा पुस्तकालय चुनते समय, कृपया ध्यान से देखें कि क्या पुस्तकालय का कार्यान्वयन नीचे सूचीबद्ध पूर्वापेक्षाओं का पालन करता है:

  • एक विश्वसनीय वादा पुस्तकालय शाल सुरक्षित होना चाहिए!

    यह सभी अतुल्यकालिक प्रसंस्करण के बारे में है, और हम कई सीपीयू का उपयोग करना चाहते हैं और जब भी संभव हो अलग-अलग थ्रेड पर निष्पादित करें। सावधान रहें, अधिकांश कार्यान्वयन थ्रेड सुरक्षित नहीं हैं!

  • हैंडलर SHALL को अतुल्यकालिक रूप से बुलाया जाना चाहिए जो कॉल-साइट का सम्मान करता है! हमेशा, और कोई बात नहीं!

    किसी भी सभ्य कार्यान्वयन को अतुल्यकालिक कार्यों को लागू करते समय एक बहुत ही सख्त पैटर्न का पालन करना चाहिए। कई कार्यान्वयन "का अनुकूलन" मामले में, जहां एक हैंडलर द्वारा सक्रिय किया जाएगा करते हैं तुल्यकालिक जब वादा पहले से ही हल हो गई है जब हैंडलर पंजीकृत होगा। यह सभी प्रकार के मुद्दों का कारण बन सकता है। देखें Zalgo जारी नहीं करते!

  • एक वादे को रद्द करने के लिए एक तंत्र भी होना चाहिए।

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


1
यह सबसे लंबे समय तक गैर-उत्तर के लिए पुरस्कार प्राप्त करता है। लेकिन ए फॉर प्रयास :-)
ट्रैवलिंग मैन

3

मुझे एहसास है कि यह एक पुराना सवाल है लेकिन मुझे इसका जवाब देना होगा क्योंकि मेरा जवाब दूसरों से अलग है।

उन लोगों के लिए जो यह कहते हैं कि यह व्यक्तिगत प्राथमिकता की बात है, मुझे असहमत होना पड़ेगा। एक अच्छा, तार्किक, एक से दूसरे को पसंद करने का कारण है ...

पूरा होने की स्थिति में, आपका ब्लॉक दो वस्तुओं को सौंप दिया जाता है, एक सफलता का प्रतिनिधित्व करता है, जबकि दूसरा विफलता का प्रतिनिधित्व करता है ... तो यदि आप शून्य हैं तो आप क्या करते हैं? यदि दोनों का मूल्य हो तो आप क्या करते हैं? ये ऐसे सवाल हैं जिनका संकलन समय पर किया जा सकता है और जैसे उन्हें होना चाहिए। दो अलग-अलग ब्लॉक होने से आप इन सवालों से बचते हैं।

अलग-अलग सफलता और विफलता ब्लॉक होने से आपका कोड वैधानिक रूप से सत्यापित हो जाता है।


ध्यान दें कि स्विफ्ट के साथ चीजें बदल जाती हैं। इसमें, हम एक Eitherएनुम की धारणा को लागू कर सकते हैं ताकि एकल समापन ब्लॉक को एक वस्तु या एक त्रुटि होने की गारंटी हो, और उनमें से बिल्कुल एक होना चाहिए। इसलिए स्विफ्ट के लिए, एक एकल ब्लॉक बेहतर है।


1

मुझे लगता है कि यह व्यक्तिगत पसंद होने के लिए खत्म हो रहा है ...

लेकिन मैं अलग सफलता / विफलता ब्लॉक पसंद करता हूं। मुझे सफलता / असफलता के तर्क को अलग करना पसंद है। यदि आपको सफलता / असफलता मिली थी, तो आप कुछ ऐसा करेंगे जो अधिक पठनीय होगा (कम से कम मेरी राय में)।

इस तरह के घोंसले के शिकार के एक अपेक्षाकृत चरम उदाहरण के रूप में, यहाँ कुछ रूबी इस पैटर्न को दिखा रही है।


1
मैंने दोनों की नेस्टेड चेन देखी है। मुझे लगता है कि वे दोनों भयानक दिखते हैं, लेकिन यह मेरी निजी राय है।
जेफरी थॉमस

1
लेकिन और कैसे आप async कॉल श्रृंखला कर सकते हैं?
फ्रैंक शियरर

मैं आदमी नहीं जानता ... मुझे नहीं पता। जिस कारण से मैं पूछ रहा हूं, उसका एक हिस्सा यह है कि मुझे यह पसंद नहीं है कि मेरा कोई भी एसिंक्स कोड कैसा दिखता है।
जेफरी थॉमस

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

इस ObjC वादे के कार्यान्वयन में आपकी रुचि हो सकती है: github.com/couchdeveloper/RXPromise
e1985

0

यह एक पूर्ण मैथुन की तरह लगता है, लेकिन मुझे नहीं लगता कि यहां कोई सही उत्तर है। मैं केवल पूर्ण ब्लॉक के साथ गया क्योंकि सफलता / विफलता ब्लॉकों का उपयोग करते समय त्रुटि से निपटने के लिए अभी भी सफलता की स्थिति में काम करना पड़ सकता है।

मुझे लगता है कि अंतिम कोड कुछ ऐसा दिखाई देगा

[target taskWithCompletion:^(id object, NSError *error) {
    if (error) {
        // Oh noes! report the failure.
    } else if (![target validateObject:&object error:&error]) {
        // Oh noes! report the failure.
    } else {
        // W00t! I've got my object
    }
}];

या केवल

[target taskWithCompletion:^(id object, NSError *error) {
    if (error || ![target validateObject:&object error:&error]) {
        // Oh noes! report the failure.
        return;
    }

    // W00t! I've got my object
}];

कोड और घोंसले के शिकार का सबसे अच्छा हिस्सा खराब नहीं होता है

[target taskWithCompletion:^(id object, NSError *error) {
    if (error || ![target validateObject:&object error:&error]) {
        // Oh noes! report the failure.
        return;
    }

    [object objectTaskWithCompletion:^(id object2, NSError *error) {
        if (error || ![object validateObject2:&object2 error:&error]) {
            // Oh noes! report the failure.
            return;
        }

        // W00t! I've got object and object 2
    }];
}];

मुझे लगता है कि मैं थोड़ी देर के लिए पोछा जाऊंगा।

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