[JavaScript] yield promise
3140 ワード
GeneratorとPromiseを混合して使用すると、非同期のコードを同期で書くことができる不思議な効果が得られます.
注:(1)
(2)呼び出し
//1. spawn
function spawn(generatorFunc){
function continuer(verb,arg){
var result;
try{
//6. iterator['next'](undefined), iterator.next(undefined);
//8. yield {done:true/false,value:promise},
// result.value yield promise
//12. iterator['next'](promise ),
// next yield
result=iterator[verb](arg);
}catch(err){
return Promise.reject(err);
}
//9. generator , generator return 。
if(result.done){
return result.value;
}else{
//10. promise continuer->onFulfilled->spawn
// , task queue promise fulfilled
//……
//11. promise fulfilled , promise , onFulfilled
// 'next' "promise " continuer
return Promise.resolve(result.value).then(onFulfilled,onRejected);
}
}
//3. ,
var iterator=generatorFunc();
//4.
// continuer this continuer, 'next'
var onFulfilled=continuer.bind(continuer,'next');
var onRejected=continuer.bind(continuer,'throw');
//5. 'next' continuer, arg===undefined
return onFulfilled();
}
//2. spawn
spawn(function*(){
try{
//7. iterator.next , yield
// getJSON promise
//13. yield "promise "
// "promise " story,
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)呼び出し
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}