[JavaScript] yield promise

GeneratorPromise混合使用的時候,會產(chǎn)生神奇的效果
可以用同步的方式書寫異步的代碼。

//1. 定義spawn
function spawn(generatorFunc){
    function continuer(verb,arg){
        var result;

        try{

            //6. 調(diào)用iterator['next'](undefined),即iterator.next(undefined);

            //8. yield返回一個{done:true/false,value:promise},
            //所以result.value的值就是yield表達式后面那個promise了

            //12. 調(diào)用iterator['next'](promise的結果值),會導致生成器中的代碼繼續(xù)執(zhí)行
            //并把next的參數(shù)值當做yield的返回值
            result=iterator[verb](arg);
        }catch(err){
            return Promise.reject(err);
        }

        //9. 判斷generator是否已執(zhí)行完,如果執(zhí)行完返回generator的return值。
        if(result.done){
            return result.value;
        }else{

            //10. 返回一個新的promise作為continuer->onFulfilled->spawn的返回值
            //這時候主線程執(zhí)行完了,等待task queue中有promise fulfilled
            //……
            //11. promise fulfilled了,會拿promise的結果值,調(diào)用onFulfilled函數(shù)
            //相當于用'next'和"promise的結果值"調(diào)用continuer
            return Promise.resolve(result.value).then(onFulfilled,onRejected);
        }
    }

    //3. 生成一個迭代器,這時生成器中的代碼還未執(zhí)行
    var iterator=generatorFunc();

    //4. 返回一個新函數(shù)
    //執(zhí)行結果相當于讓continuer的this指向continuer,第一個參數(shù)為'next'
    var onFulfilled=continuer.bind(continuer,'next');
    var onRejected=continuer.bind(continuer,'throw');

    //5. 相當于以'next'為參數(shù)調(diào)用continuer,其中arg===undefined
    return onFulfilled();
}

//2. 用一個生成器作為參數(shù)調(diào)用spawn
spawn(function*(){
    try{

         //7. 調(diào)用iterator.next才開始執(zhí)行生成器中的代碼,執(zhí)行到y(tǒng)ield后返回
        //其中getJSON的返回值是一個promise

        //13. yield的返回值就是"promise的結果值"了
        //把"promise的結果值"賦值給story,完成了用同步代碼實現(xiàn)異步功能
        let story=yield getJSON('story.json');
        addHtmlToPage(story.heading);

        let chapterPromises=story.chapterUrls.map(getJSON);

        for(let chapterPromise of chapterPromises){
            let chapter=yield chapterPromise;
            addHtmlToPage(chapter.html);
        }

        addTextToPage('All done');
    }catch(err){
        addTextToPage('Argh, broken: '+err.message);
    }

    document.querySelector('.spinner').style.display='none';
});

注:
(1)yield v;不會把v直接返回給iterator.next()
而是返回{done:true/false,value:v}

var generator=function*(){
    yield 1;
    return 2;
}

var iterator=generator();
iterator.next();    //{done:false,vaue:1}
iterator.next();    //{dont:true,value:2}
iterator.next();    //{dont:true,value:undefined}
iterator.next();    //{dont:true,value:undefined}

(2)調(diào)用iterator.next,可以傳值,作為yield的返回值

function* gen(){
    var v1=yield 1;
    console.info(v1);//2
    
    var v2=yield 2;
    console.info(v2);    //3

    return 0;
}

variter=gen();

var t1=iter.next(1);
console.warn(t1);    //Object {value: 1, done: false}

var t2=iter.next(2);    //2
console.warn(t2);    //Object {value: 2, done: false}

var t3=iter.next(3);    //3
console.warn(t3);    //Object {value: 0, done: true}
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容