6

js中yield实现同步原理

 3 years ago
source link: https://laboo.top/2019/11/25/jsyield/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

js中yield实现同步原理

Posted on

2019-11-25 Edited on 2021-12-15 In 技术分享

在js中需要将异步方法同步的时候, 经常使用的是asyncawait, 或者用Promise

偶然在dvajs中看到其使用yield迭代器实现了同步的效果, 例如

function* f(){
var a = Promise.resolve(1);
console.log(a); // Promise
var ra = yield a;
console.log(ra); // 1
var b = Promise.resolve(2);
console.log(b); // Promise
var rb = yield b;
console.log(rb); // 2
return "success";
}

当然直接运行不能得到预期的效果, Promise没用同步执行, yield返回的结果也是undefined, 因为还缺少对其的一层封装, 或者说还缺少个执行器

var it = f();
it.next();
it.next();
it.next();

传统的迭代器, 是这样使用的

function* range(){
for(let i=0;i<n;i++){
yield i;
}
}
var it = range();
console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.next().value); // 2

如下封装, 在每一次yield返回的Promisethen中进行下一次迭代, 并把结果传入 g.next(r), 迭代函数的next(r)中的参数r会成为函数体中yield标识的表达式的返回值, 从而达到类似await的效果

function async(g) {
var ctx = this;
return new Promise(function(resolve, reject) {
g = g.apply(ctx);
next();
function next(r) {
var result = g.next(r);
if (result.done){
return resolve(result.value);
}
result.value.then(next);
}
});
}

async(function*(){
var a = Promise.resolve(1);
console.log(a); // Promise
var ra = yield a;
console.log(ra); // 1
var b = Promise.resolve(2);
console.log(b); // Promise
var rb = yield b;
console.log(rb); // 2
return "success";
}).then(v=>{
console.log(v) // success
});


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK