下面实现了一个控制流包装器co
,使异步代码只能由yield
关键字来描述。
这基本上是async
/await
在ESwhatever的引擎盖下所做的吗?
co(function*() {
console.log('...');
yield one();
console.log('...');
yield two();
})
function co(gFn) {
var g = gFn();
return Promise.resolve()
.then(go);
function go() {
var result = g.next();
if(result.done) {
return;
}
if(isPromise(result.value)) {
return result.value.then(go); // Promises block until resolution.
}
return Promise.resolve(result);
}
}
function isPromise(o) {
return o instanceof Promise;
}
function one() {
return new Promise(resolve => setTimeout(() => (console.log('one'), resolve()), 1000));
}
function two() {
return new Promise(resolve => setTimeout(() => (console.log('two'), resolve()), 1000));
}
编辑:
根据我为考虑返回值而更新的答复:
co(function*() {
console.log('...');
const result1 = yield one();
console.log('result1: ', result1);
const result2 = yield two();
console.log('result2: ', result2);
const result3 = yield[one(), two()];
console.log('result3: ', result3);
const result4 = yield{
one: one(),
two: two()
};
console.log('result4: ', result4);
})
function co(gFn) {
var g = gFn();
return Promise.resolve().then(go);
function go() {
var result = g.next(...arguments);
if (isPromise(result.value)) {
return result.value.then(go);
}
if (Array.isArray(result.value)) {
return Promise.all(result.value).then(go);
}
if (isObject(result.value)) {
var o = {};
var promises = Object.keys(result.value).map(k=>result.value[k].then(r=>o[k] = r));
return Promise.all(promises).then(()=>o).then(go);
}
return Promise.resolve(result);
}
}
function isPromise(o) {
return o instanceof Promise;
}
function isObject(val) {
return val && (Object === val.constructor);
}
function one() {
return new Promise(resolve=>setTimeout(()=>(console.log('one'),
resolve('result 1')), 1000));
}
function two() {
return new Promise(resolve=>setTimeout(()=>(console.log('two'),
resolve('result 2')), 1000));
}
发布于 2017-04-21 16:29:20
这基本上是ESwhatever中异步/等待在幕后所做的吗?
不怎么有意思。这是一种不同的方法来做同样的事情。async/await
变成的更像是
async function foo() {
const bar = await Bar();
bar++;
const baz = await Baz(bar);
return baz;
}
变成了
function foo() {
return Bar()
.then(bar => {
bar++;
return Baz(bar)
.then(baz => {
return baz;
});
});
}
发布于 2017-04-21 16:34:05
第三阶段草案/2016年1月26日异步函数提供了三种模式的示例:Promise
;Generator
;Async Functions
;其中不同的方法基本上产生相同的结果。
Examples# 以下面的例子为例,首先使用承诺编写。此代码将元素上的一组动画链接起来,在动画中出现异常时停止,并返回最终成功执行的动画产生的值。 函数chainAnimationsPromise(elem,动画){ let ret = null;let p= currentPromise;for(const anim of动画){p=p.then(函数(Val){ ret = val;}) }返回p.catch(函数(E){ /*忽略并继续前进*/ }).then(函数()););} 已经有了承诺,代码已经从直接回调风格中得到了很大的改进,这种循环和异常处理是很有挑战性的。 Task.js和类似的库提供了一种方法来使用生成器来进一步简化代码,保持相同的含义: 函数chainAnimationsGenerator(elem,动画){返回子程序(函数*()){ let ret = null;尝试{ for(const anim of动画){ ret =产生anim(elem);} /* (E){/*忽略并继续返回ret;};} 这是一个显著的进步。所有超出代码语义内容的承诺样板都被删除,内部函数的主体表示用户意图。但是,还有一个外层的样板可以将代码包装在一个额外的生成器函数中,并将其传递给库以转换为承诺。这一层需要在使用此机制产生承诺的每个功能中重复。这在典型的异步Javascript代码中是如此常见,因此消除对剩余样板的需求是有价值的。 使用异步函数,将删除所有剩余的样板,只在程序文本中留下语义上有意义的代码: 异步函数chainAnimationsAsync(elem,动画){ let ret = null;尝试{ for(const of动画){ ret =等待anim(elem);} /* (E){/*忽略并继续返回ret;}
https://stackoverflow.com/questions/43547606
复制相似问题