我在这里关注博客文章: http://www.tivix.com/blog/making-promises-in-a-synchronous-manner
表示生成器可用于同步承诺执行。
我知道这是一个不好的做法 - 我们正在使用类似GWT的框架(准确地说是Urweb),它现在只能理解同步的javascript函数返回值。
遵循该文章的代码
{
'use strict';
let asyncTask = () =>
new Promise(resolve => {
let delay = 1000;
setTimeout(function () {
resolve(delay);
}, delay);
});
let makeMeLookSync = fn => {
let iterator = fn();
let loop = result => {
!result.done && result.value.then(res =>
loop(iterator.next(res)));
};
loop(iterator.next());
};
console.log(1);
makeMeLookSync(function* () {
let result = yield asyncTask();
console.log(result);
});
console.log(3);
}
给出以下输出:
1
3
1000
但如果承诺是同步的,那么输出应该是
1
1000
3
我做错了吗?或者是不可能使用生成器同步承诺?
答案 0 :(得分:2)
我做错了吗?
是。应该出现同步的所有代码都必须进入生成器函数:
makeMeLookSync(function* () {
let result = yield asyncTask();
console.log(result);
console.log(3);
});
或者是否不可能使用生成器同步承诺?
您可以永远使异步代码同步。生成器允许您编写看起来同步的代码,这意味着(并且在您链接的文章中提到)代码从上到下执行:
尽可能简单地说:async JavaScript在读取时不执行 - 从上到下。
但是,如上所述,这只适用于发电机内部。 yield
关键字允许您以同步方式编写代码。请注意,该函数的名称为makeMeLookSync
,而不是makeMeSync
。
话虽如此,ES2017引入了async
functions基本上做同样的事情,没有生成器和跑步者来执行生成器:
{
'use strict';
let asyncTask = () =>
new Promise(resolve => {
let delay = 1000;
setTimeout(function() {
resolve(delay);
}, delay);
});
console.log(1);
(async function() {
let result = await asyncTask();
console.log(result);
console.log(3);
}());
}