以下实现了一个控制流包装器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));
}

答案 0 :(得分:4)
这基本上是什么async / await在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;
});
});
}
答案 1 :(得分:3)
Stage 3 Draft / January 26, 2016
Async Functions提供了三种模式的示例; Promise
; Generator
; Async Functions
;不同的方法基本上产生相同的结果
采用以下示例,首先使用Promises编写。这段代码 链接元素上的一组动画,当有元素时停止 动画中的异常,并返回由...生成的值 最终成功执行的动画。
function chainAnimationsPromise(elem, animations) { let ret = null; let p = currentPromise; for(const anim of animations) { p = p.then(function(val) { ret = val; return anim(elem); }) } return p.catch(function(e) { /* ignore and keep going */ }).then(function() { return ret; }); }
已经使用promises,代码从直接回调样式得到了很大改进,其中这种循环和异常处理是 有挑战性的。
Task.js和类似的库提供了一种使用生成器进一步的方法 简化代码保持相同的含义:
function chainAnimationsGenerator(elem, animations) { return spawn(function*() { let ret = null; try { for(const anim of animations) { ret = yield anim(elem); } } catch(e) { /* ignore and keep going */ } return ret; }); }
这是一项显着的改进。除了代码的语义内容之外的所有承诺样板都被删除了 内部函数的主体表示用户意图。但是,有 一个样板的外层,用于将代码包装在一个附加的中 生成器函数并将其传递给库以转换为promise。 需要在使用它的每个函数中重复该层 产生承诺的机制。这在典型的异步中很常见 Javascript代码,有消除需要的价值 剩下的样板。
使用异步功能,删除所有剩余的样板, 只留下程序文本中具有语义意义的代码:
async function chainAnimationsAsync(elem, animations) { let ret = null; try { for(const anim of animations) { ret = await anim(elem); } } catch(e) { /* ignore and keep going */ } return ret; }