2016-01-12 14 views
7

मैं बेहतर ढंग से समझने की कोशिश कर रहा हूं कि जावास्क्रिप्ट में async function तकनीकी रूप से क्या है, भले ही मैं मूल रूप से उनको कैसे उपयोग कर सकूं।ES7 async फ़ंक्शन और वादे के बीच तकनीकी अंतर?

async के लिए कई परिचय/belive एक async समारोह मूल रूप से सिर्फ एक वादा है, लेकिन यह स्पष्ट रूप से मामला (कम से कम Babel6-transpiled code साथ नहीं) नहीं है कि बनाने का इंतजार:

async function asyncFunc() { 
    // nop 
} 

var fooPromise = new Promise(r => setTimeout(r, 1)); 

console.clear(); 

console.log("typeof asyncFunc is", typeof asyncFunc); // function 
console.log("typeof asyncFunc.next is", typeof asyncFunc.next); // undefined 
console.log("typeof asyncFunc.then is", typeof asyncFunc.then); // undefined 

console.log("typeof fooPromise is", typeof fooPromise); // object 
console.log("typeof fooPromise.next is", typeof fooPromise.next); // undefined 
console.log("typeof fooPromise.then is", typeof fooPromise.then); // function 

फिर भी, यह निश्चित रूप से संभव है await पर एक वादा, जैसे await fooPromise()

  • एक async funtion अपने आप की बात है और await बस वादे के साथ संगत है?

  • और, क्या रनटाइम पर एक सरल function और async function के बीच अंतर करने का कोई तरीका है (एक बेबेल-संगत तरीके से)?

उत्तर

9

एक async समारोह एक समारोह है कि एक वादा देता है। यह ऐसे मामलों में जहां आप एक के बाद एक हो रहा अतुल्यकालिक कार्यों का एक समूह है साथ में सहायक है:

function asyncFunc() { 
    return doSomethingAsync() // doSomethingAsync() returns a promise 
    .then(() => { 
     // do some stuff 
     return doSomethingElseAsync(); // returns a promise 
    }) 
    .then(something => { 
     // do some stuff 
     return doSomethingElseEntirelyAsync(something); // returns a promise 
    }); 
} 

बदल जाता है

async function asyncFunc() { 
    await doSomethingAsync(); // awaits for a promise 
    // do some stuff 
    let something = await doSomethingElseAsync(); // awaits for a promise 
    // do some stuff 
    return doSomethingElseEntirelyAsync(something); // returns the final promise 
    // Note that even if you return a value, like return 5, the function as a whole 
    // still returns a promise! 
} 

को यह एक बहुत बेहतर पढ़ता है, और आप की कोशिश की तरह सामान्य उपकरणों का उपयोग कर सकते हैं/पकड़ो और उनके साथ काम करने के लिए loops के लिए, भले ही वे async हैं।

Async फ़ंक्शन वादे के प्रतिस्थापन नहीं हैं, वे उन विशिष्ट मामलों को संभालने के लिए चीनी हैं, जहां आपके पास कई अनुक्रमिक असीमित क्रियाएं हैं।

क्योंकि await मूल रूप से बस "इस वादे के लिए इंतजार है" है, तो आप अभी भी शांत एकत्रीकरण तरीकों Promise.all() और Promise.race() की तरह इस्तेमाल करते हैं और कई (या कई के पहले) वादों का परिणाम के लिए इंतजार कर सकते हैं।

मैं रनटाइम में दोनों को अलग करने के तरीके से परिचित नहीं हूं क्योंकि कक्षाओं की तरह, एसिंक फ़ंक्शन केवल वादे के शीर्ष पर चीनी हैं। (हालांकि फ़ंक्शन के .toString का उपयोग करने जैसे हैंक हो सकते हैं और परिणामों को पार्स कर सकते हैं, मैं उन पर भरोसा नहीं करता)।

+0

धन्यवाद, बहुत समझ में आता है। इसलिए, अनिवार्य रूप से, 'asyncFunc' एक वादा नहीं है, लेकिन' asyncFunc() 'है - या अन्य शब्दों के साथ: 'asofcFunc टाइप करें)। फिर ==" फ़ंक्शन "' –

+0

यह बिल्कुल सही है। –

0

जोड़ी async/await एक तंत्र है कि आप एक तुल्यकालिक शैली में और मेरी विनम्र राय में यह अब तक एसिंक्रोनस कोड से निपटने के लिए सबसे सरल और पठनीय वाक्य रचना है async कोड लिखने करते हैं (यह भी this article देखें)। वाक्यविन्यास की शक्ति वास्तव में await काम करता है। लेकिन फ़ंक्शन के बॉडी के अंदर await का उपयोग करने के लिए, फ़ंक्शन को async के साथ उपसर्ग करना होगा।

यदि आपको अधिक जानकारी चाहिए तो spec for async/await here है।

बैबेल 5 में वर्तमान कार्यान्वयन https://github.com/facebook/regenerator पर आधारित है।आप transpiled code में देख सकते हैं कार्य करने के लिए संकलित किया गया है:

function asyncFunc(which, one, two) { 
    return regeneratorRuntime.async(function asyncFuncMaybe$(context$1$0) { 
... 

आप कोलाहल के babel-regenerator-runtime पैकेज में खुदाई यदि आप फेसबुक के कोड पाते हैं। line 205 पर आप पाते हैं:

// Note that simple async functions are implemented on top of 
// AsyncIterator objects; they just return a Promise for the value of 
// the final result produced by the iterator. 
runtime.async = function(innerFn, outerFn, self, tryLocsList) { 
... 

आदेश में async/await कोलाहल जरूरतों ES5 को transpile करने के लिए कोड को पुनर्व्यवस्थित करने के लिए क्या इसलिए हम ट्रैक रख सकते हैं, जहां हम समारोह के निष्पादन के दौरान कर रहे हैं और AsyncIterator उद्देश्य यह है कि ट्रैक रखने के है उस राज्य का।

बेबेल 6 आपको अधिक विकल्प देता है और आपको उस क्रियान्वयन को चुनने देता है जिसका आप उपयोग करना चाहते हैं। देखें Transpile Async Await proposal with Babel.js?

तो आपके प्रश्नों के बारे में:

  • async/await दोनों अपने आप की बात कर रहे हैं। कल्पना के अनुसार, उन्हें वादे के साथ काम करना चाहिए। विशेष रूप से आप एक वचन पर await कर सकते हैं और जब आप async फ़ंक्शन निष्पादित करते हैं, तो यह आपको एक वादा वापस कर देगा।
  • चूंकि async फ़ंक्शन को एक वादा वापस करने के लिए पारदर्शी किया गया है, इसलिए इसे एक नो-एसिंक फ़ंक्शन से अलग करने का एक सीधा तरीका नहीं है जो एक वादा वापस कर देता है। आपका fooPromisevar fooPromiseFunc = function() {return new Promise(r => setTimeout(r, 1))}; जैसा दिखना चाहिए जो fooPromiseFunc और asyncFunc को ब्लैक बॉक्स संभावित से अलग करने योग्य बनाता है। वे दोनों कार्य हैं जो एक वादा वापस करते हैं। क्या कारण है कि आप रनटाइम पर async और नो-एसिंक फ़ंक्शन को अलग करना चाहते हैं? व्यावहारिक रूप से उनका उपयोग उसी तरह किया जा सकता है, इसलिए मुझे नहीं पता कि आपको उन्हें अलग-अलग खतरे क्यों डालना होगा। डीबग प्रयोजनों के लिए यदि आपको वास्तव में यह पता लगाना है कि कोई फ़ंक्शन async परिभाषित किया गया है, तो बेबेल 5 में आप (asyncFunc+"").indexOf('regeneratorRuntime.async') > 0 या अधिक सटीक नियमित अभिव्यक्ति जैसे कुछ उपयोग कर सकते हैं। लेकिन यह वास्तव में हैकी है और मैं डिबगिंग या अध्ययन के बाहर किसी संदर्भ में उपयोग नहीं करता।
+0

गहराई से स्पष्टीकरण के लिए धन्यवाद। पुन: * कारण क्या है कि आप रनटाइम पर एसिंक और नो-एसिंक फ़ंक्शन को अलग करना चाहते हैं? *: वास्तव में मैं केवल सामान्य कॉलबैक को वादे से अलग करना चाहता था (अंत में 'एक्सप्रेस' वादा/async- अनुकूल में स्वचालित तरीका)। अब जब मैं जानता हूं कि चीजें कैसे काम करती हैं, यह सब मेरे लिए स्पष्ट है और असल में मैं 'एक्सप्रेस' के लिए एक पूरी तरह से काम कर रहा (प्रयोगात्मक) पैच बनाने में सक्षम था। –

+0

इसके लिए आप इन 2 लिंक को उपयोगी पा सकते हैं: https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/ और https://github.com/luin/express-promise –

+0

उन लिंक के लिए धन्यवाद। मैं उन्हें पहले से ही इस प्रश्न को पोस्ट करने से पहले जानता था और उत्तरों की मदद से मुझे एक स्पष्ट रैपर फ़ंक्शन के उपयोग से बचने का एक तरीका मिला और अभी भी वही परिणाम मिलता है। –

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