डार्ट एक FutureOr वर्ग प्रदान करता है, जो लिखने की अनुमति देता है :

FutureOr<int> future;

future = 42; // valid
future = Future.value(42); // also valid

मुझे लगता है कि FutureOr के लिए उपयोगी होगा यदि मान को समकालिक रूप से पढ़ा जा सकता है, तो ईवेंट लूप के कारण होने वाले अनावश्यक विलंब को हटा दें।

लेकिन ऐसा प्रतीत नहीं होता है, जैसा कि दिखाया गया है:

import 'dart:async';

void main() async {
  print('START');
  futureOrExample();
  print('END');
}

void futureOrExample() async {
  FutureOr<int> futureOr = 42;
  print('before await');
  await futureOr;
  print('end await');
}

जो प्रिंट करता है:

START
before await
END
end await

जब मैं उम्मीद करूंगा:

START
before await
end await
END

उस स्थिति में, FutureOr (या अधिक सामान्यतः await 42) इस तरह से काम करते हैं?

इसी तरह, उसमें FutureOr का उद्देश्य क्या है? क्योंकि यह भविष्य जैसा ही परिणाम देता है। ?

मुझे पता है कि मैं वांछित परिणाम प्राप्त करने के लिए SynchronousFuture का उपयोग कर सकता हूं, लेकिन मैं मैं बस यह समझने की कोशिश कर रहा हूं कि FutureOr

35
Rémi Rousselet 6 पद 2019, 15:29
अपेक्षित परिणाम प्राप्त करने के लिए आपको futureOrExample() में प्रतीक्षा जोड़ने की आवश्यकता है; मुख्य () फ़ंक्शन के अंदर
 – 
Lucas Chwe
2 सितंबर 2020, 21:16

3 जवाब

सबसे बढ़िया उत्तर

डार्ट 2 के साथ शुरू किए गए FutureOr का उपयोग आपको उस बिंदु पर या तो एक मूल्य या भविष्य प्रदान करने की अनुमति देता है जहां मौजूदा डार्ट 1 एपीआई सुविधा के लिए एक ही चीज़ की अनुमति देता है, केवल इस तरह से हो सकता है स्थिर रूप से टाइप किया गया।

प्रामाणिक उदाहरण Future.then है। Future<T> पर हस्ताक्षर Future<R> then<R>(FutureOr<R> action(T value), {Function onError}) है।

विचार यह है कि आप भविष्य के मूल्य पर एक क्रिया कर सकते हैं जो या तो तुल्यकालिक या अतुल्यकालिक है। मूल रूप से एक then फ़ंक्शन था जो एक सिंक्रोनस कॉलबैक लेता था और एक chain फ़ंक्शन जो एक एसिंक्रोनस कॉलबैक लेता था, लेकिन वह काम करने के लिए अत्यधिक परेशान था, और अच्छी डार्ट 1 शैली में, एपीआई को कम कर दिया गया था one then मेथड जिसने dynamic को वापस करने के लिए एक फंक्शन लिया, और फिर उसने जाँच की कि यह भविष्य है या नहीं।

डार्ट 1 में आपको किसी मूल्य या भविष्य को वापस करने की अनुमति देना आसान था। डार्ट 2 उतना उदार नहीं था, इसलिए FutureOr प्रकार को मौजूदा एपीआई को काम करने की अनुमति देने के लिए पेश किया गया था। अगर हमने शुरुआत से एपीआई लिखा होता, तो शायद हम कुछ और करते, लेकिन मौजूदा एसिंक्रोनस कोड बेस को पूरी तरह से अलग करने के लिए माइग्रेट करना एक विकल्प नहीं था, इसलिए FutureOr टाइप को टाइप-लेवल हैक के रूप में पेश किया गया था। .

await ऑपरेशन को मूल रूप से किसी भी वस्तु पर काम करने के लिए परिभाषित किया गया था, FutureOr के अस्तित्व में आने से बहुत पहले। निरंतरता और छोटे कोड के लिए, एक await e जहां e का मूल्यांकन एक गैर-भविष्य के लिए किया जाता है, उस मूल्य को भविष्य में लपेट देगा और उसका इंतजार करेगा। इसका मतलब है कि एक मूल्य पर केवल एक त्वरित और पुन: प्रयोज्य जांच है (क्या यह भविष्य है, यदि इसे लपेटा नहीं गया है), और फिर शेष कोड समान है। केवल एक कोड-पथ है। यदि await गैर-Future मानों पर समकालिक रूप से काम करता है, तो await के माध्यम से चलने वाला एक तुल्यकालिक कोड पथ होना चाहिए, साथ ही एक अतुल्यकालिक पथ भविष्य की प्रतीक्षा कर रहा होगा। यह संभावित रूप से कोड आकार को दोगुना कर देगा, उदाहरण के लिए जावास्क्रिप्ट को संकलित करते समय (या इससे भी बदतर, यदि एक ही नियंत्रण प्रवाह में अधिक await थे, तो आप एक निष्पक्ष कार्यान्वयन के लिए घातीय झटका प्राप्त कर सकते हैं)। यहां तक ​​​​कि अगर आप निरंतरता फ़ंक्शन को समकालिक रूप से कॉल करने से बचते हैं, तो यह कुछ पाठकों के लिए भ्रमित करने वाला होगा कि एक await एक एसिंक्रोनस गैप को नहीं पेश करेगा। इसके आसपास एक गलती दौड़ की स्थिति या गलत क्रम में होने वाली चीजों का कारण बन सकती है।

तो, मूल डिजाइन, FutureOr से पहले, सभी await संचालन को वास्तव में प्रतीक्षा करना था।

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

14
lrn 9 पद 2019, 18:24
मैं यह देखने के लिए किसी भी FutureOr impl वर्ग के स्रोतों को खोजने का प्रयास कर रहा था कि इसे कैसे कार्यान्वित किया जाता है लेकिन ऐसा करने में सक्षम नहीं था। क्या आप बता सकते हैं कि क्या यह संभव है?
 – 
Alexander Arendar
22 जून 2020, 13:05
1
यह संभव नहीं है। FutureOr प्रकार वर्ग नहीं है। FutureOr<X> वास्तव में एक संघ प्रकार है जो या तो एक Future<X> या एक X मान का प्रतिनिधित्व करता है। जैसे, यह उन दोनों प्रकारों का एक सुपरटाइप है, और इसे कम से कम इस तरह के सुपरटाइप के रूप में परिभाषित किया गया है (इसे किसी भी प्रकार के उपप्रकार के रूप में परिभाषित किया गया है जो दोनों का एक सुपरटाइप भी है Future<X> और X)। प्रकार के लिए कोई वर्ग संबंधित नहीं है, जैसे फ़ंक्शन प्रकारों से संबंधित कोई वर्ग नहीं है, dynamic, void या Never। वे सिर्फ प्रकार हैं।
 – 
lrn
23 जून 2020, 01:00
धन्यवाद, इसने मुझे वास्तव में हैरान कर दिया। अब मैं देखता हूं कि यह एक विशेष मामला है जिसे टाइप सिस्टम में तार दिया गया है।
 – 
Alexander Arendar
23 जून 2020, 01:14

await कीवर्ड हमेशा फ़ंक्शन निष्पादन को लॉक करता है।

लिखना:

await 42

के बराबर है:

await Future.value(42)

इसका कारण:

  • जावास्क्रिप्ट में await इस प्रकार काम करता है
  • यह await के व्यवहार को सुसंगत बनाता है।

अब, FutureOr का उद्देश्य क्या है?

FutureOr का इरादा कभी भी await को समकालिक बनाने के तरीके के रूप में नहीं किया गया था।

इसके बजाय, यह Future का कार्यान्वयन विवरण है।

FutureOr के बिना, निम्नलिखित लिखना संकलित नहीं होगा:

Future(() {
  return 42; // compile error, not a Future
});

Future<int> future;
future.then((value) {
  return value * 2; // compile error, not a Future
});

इसके बजाय, हमें सभी मानों को Future.value में इस प्रकार लपेटना होगा:

Future<int> future;
future.then((value) {
  return Future.value(value * 2);
});
3
Rémi Rousselet 8 पद 2019, 08:23
यह एक जेएस विषय नहीं है! यह डार्ट भाई है।
 – 
Amir Hossein
18 नवम्बर 2020, 09:24

चर्चा में देर से आते हैं। मेरी डार्ट समझ को अद्यतन करना - मेरे सी++/जेएस-इश दृष्टिकोण को क्षमा करें।

ऐसा लगता है कि सिंगलटन दीक्षा के लिए यह उपयोगी होगा। निम्नलिखित पर विचार करें:

import 'dart:async';

class AClass {
  static String _info = '';
  
  static FutureOr<String> get info async {
    if (_info.isEmpty) {
      print('--> is empty...');
      _info = await Future.delayed(Duration(seconds:2), 
                                   () => "I'm alive!!");
    }
    else {
      print('--> not empty');
    }
    
    return _info;
  }
}

Future<void> main() async {
  String info = await AClass.info;
  print('Fist call: ' + info);
  
  info = await AClass.info;
  print('Second call: ' + info);
}

यह अपेक्षित रूप से काम करता है - किसी भी मामले में, चाहे _info सदस्य को तत्काल किया गया हो या नहीं, गेटर एक वैध स्ट्रिंग देता है।

यह ठीक काम करता है अगर मैं गेटटर में भी Future<String> विनिर्देशक का उपयोग करता हूं। वर्तमान कार्यान्वयन फ्यूचरऑर को ज्यादातर एक स्व-दस्तावेजीकरण अभ्यास की तरह लगता है (एक Future<String> या एक String... वापस कर सकता है)

लेकिन, भले ही प्रतीक्षा करें वर्तमान में हमेशा निष्पादन को लॉक कर देता है, भविष्य का अपडेट इसे अपेक्षित रूप से काम करने की अनुमति दे सकता है, इस मामले में FutureOr निर्माण का उपयोग अपडेट की उम्मीद करेगा।

(इसके अलावा: मुझे लगता है कि इस उदाहरण को Optional का उपयोग करके _info सदस्य को लपेटकर संघनित किया जा सकता है, लेकिन यह एक अलग अभ्यास है ...)

-1
rickb 21 मार्च 2021, 22:23