javascript - उपज/जनरेटर के साथ कोड प्रवाह को समझना




node.js generator (2)

मैंने जावास्क्रिप्ट जेनरेटर का इस्तेमाल करते हुए कोड के कई उदाहरण पढ़ा है जैसे कि यह एक । सरल जनरेटर का प्रयोग करके ब्लॉक मैं आ सकता हूं:

function read(path) {
    return function (done) {
        fs.readFile(path, "file", done);
    }
}

co(function *() {
    console.log( yield read("file") );
})();

यह वास्तव में file की सामग्री को प्रिंट करता है, लेकिन मेरा लटका हुआ है, जहां कहा जाता है। प्रतीत होता है कि उपज, एक कॉलबैक में लौटती है और परिणाम मान को उचित रूप से आवंटित करने के लिए (और कम से कम co के मामले में, कॉलबैक पर त्रुटि तर्क को फेंकने के लिए) लपेटने के लिए वाक्य-रचनात्मक चीनी है। क्या वाक्यविन्यास की मेरी समझ सही है?

क्या done है जब yield का उपयोग किया जाता है?


प्रतीत होता है कि उपज, एक कॉलबैक में लौटती है और परिणाम मान को उचित रूप से आवंटित करने के लिए वाक्य-क्रियात्मक चीनी है (और कम से कम सह के मामले में, कॉलबैक में त्रुटि तर्क को फेंकने)

नहीं, yield कोई वाक्यविन्यास चीनी नहीं है यह जनरेटर के मूल सिंटैक्स तत्व है जब वह जनरेटर तत्काल होता है, तो आप इसे ( .next() पर कॉल करके चला सकते हैं), और वह उस मूल्य को वापस करेगा, जो वापस लौटा था या एड को yield था। जब जनरेटर yield था, तो आप इसे बाद में फिर से जारी कर सकते हैं। next कीमतों में ये तर्क होगा कि जनरेटर के अंदर yield एक्सप्रेशन रिटर्न देता है।

केवल co मामले में, उन एसिंक कॉलबैक चीजों (और अन्य चीजों ) को "उचित" रूप से नियंत्रित किया जाता है, जो आप एसिंक नियंत्रण प्रवाह पुस्तकालय में स्वाभाविक रूप से विचार करेंगे।

क्या किया जाता है जब उपज का उपयोग किया जाता है?

आपके द्वारा पढ़ा गया आलेख के thread फ़ंक्शन का उदाहरण आपको इस का एक अच्छा प्रभाव देता है:

function thread(fn) {
  var gen = fn();
  function next(err, res) {
    var ret = gen.next(res);
    if (ret.done) return;
    ret.value(next);
  }
  next();
}

आपके कोड में, yield जनरेटर से अभिव्यक्ति read("file") की अभिव्यक्ति का मूल्य yield करता है, जब वह भाग जाता है यह ret.val हो जाता है, जो gen.next() का परिणाम है। इसके लिए, next फ़ंक्शन को पारित किया जाता है - एक कॉलबैक जो उस रिज़ल्ट के साथ जनरेटर को जारी रखेगा जो उसे पास किया गया था। आपके जनरेटर कोड में, ऐसा लगता है कि yield अभिव्यक्ति ने इस मान को वापस कर दिया है।

क्या होता है की एक "अनारोल्ड" संस्करण इस तरह लिखा जा सकता है:

function fn*() {
    console.log( yield function (done) {
        fs.readFile("filepath", "file", done);
    } );
}
var gen = fn();
var ret1 = gen.next();
var callasync = ret1.value;
callasync(function next(err, res) {
    var ret2 = gen.next(res); // this now does log the value
    ret2.done; // true now
});

मैंने इस बारे में विस्तृत व्याख्या पोस्ट की है कि जनरेटर कैसे काम करते हैं ।

एक सरलीकृत रूप में, आपका कोड co (अनुत्पादित) बिना इस तरह दिख सकता है:

function workAsync(fileName)
{
    // async logic
    var worker = (function* () {

        function read(path) {
            return function (done) {
                fs.readFile(path, "file", done);
            }
        }

        console.log(yield read(fileName));
    })();

    // driver
    function nextStep(err, result) {
        try {
            var item = err? 
                worker.throw(err):
                worker.next(result);
            if (item.done)
                return;
            item.value(nextStep);
        }
        catch(ex) {
            console.log(ex.message);
            return;
        }
    }

    // first step
    nextStep();
}

workAsync("file");

कार्य का चालक भाग workAsync अतुल्यकालिक जनरेटर ऑब्जेक्ट के माध्यम से, nextStep() कॉल nextStep() कॉल nextStep()







co