![](/img/trans.png)
[英]Javascript. Transform synchronous function as asynchronous using callbacks, promises, async/await, generators
[英]JavaScript asynchronous programming: promises vs generators
承诺和生成器允许您编写异步代码。 我不明白为什么在ECMA脚本6中同时引入了这两种机制。什么时候最好使用Promise?什么时候使用生成器?
这两种技术之间没有对立。 它们共存并很好地互补。 承诺使您能够获得尚不可用的异步操作的结果。 它解决了厄运金字塔问题。 所以代替:
function ourImportantFunction(callback) {
//... some code 1
task1(function(val1) {
//... some code 2
task2(val1, function(val2) {
//... some code 3
task3(val2, callback);
});
});
}
你可以写:
function ourImportantFunction() {
return Promise.resolve()
.then(function() {
//... some code 1
return task1(val3)
})
.then(function(val2) {
//... some code 2
return task2(val2)
})
.then(function(val2) {
//... some code 3
return task3(val2);
});
}
ourImportantFunction().then(callback);
但是即使有承诺,您也必须以异步方式编写代码-您必须始终将回调传递给函数。 编写异步代码比同步代码难得多。 即使有承诺,当代码很大时,也很难看清算法(嗯,这是非常主观的,有人可以与它争论。但是对于大多数程序员来说,我认为这是事实)。 因此,我们想以同步方式编写异步代码。 那就是发电机来帮助我们的地方。 因此,您可以编写上面的代码,而不是上面的代码:
var ourImportantFunction = spawn(function*() {
//... some code 1
var val1 = yield task1();
//... some code 2
var val2 = yield task2(val1);
//... some code 3
var val3 = yield task3(val2);
return val3;
});
ourImportantFunction().then(callback);
最简单的spawn
实现可能是这样的:
function spawn(generator) {
return function() {
var iter = generator.apply(this, arguments);
return Promise.resolve().then(function onValue(lastValue){
var result = iter.next(lastValue);
var done = result.done;
var value = result.value;
if (done) return value; // generator done, resolve promise
return Promise.resolve(value).then(onValue, iter.throw.bind(iter)); // repeat
});
};
}
如您所见, value
(某些异步函数task{N}
)必须是一个承诺。 您不能通过回调来做到这一点。
剩下要做的是在语言本身中实现spawn
技术。 因此,我们用async
替换了spawn
,并用await
替换了yield
,并开始使用ES7 async / await :
var ourImportantFunction = async function() {
//... some code 1
var val1 = await task1();
//... some code 2
var val2 = await task2(val1);
//... some code 3
var val3 = await task3(val2);
return val3;
}
我建议您观看此视频,以更全面地了解此技术和其他一些即将来临的技术。 如果该家伙对您说得太快,请放慢演奏速度(右下角的“设置”,或按[ shift
+ <
])
最好的是什么:仅仅是回调,promise或使用生成器的promise-这是一个非常主观的问题。 回调是目前可能的最快解决方案(现在,本机承诺的履行非常糟糕)。 生成器的承诺使您有机会以同步方式编写异步代码。 但是现在,它们比简单的回调要慢得多。
Promise和Generators是不同的软件模式(构造):
实际上,生成器不是异步的。
当您需要一次获取一系列值而不是每个需求一个值时,生成器很有用。 生成器将在每次调用时立即(同步)返回下一个值,直到到达序列的末尾(如果是无限序列,则返回无穷)。
当您需要“推迟”可能尚未计算(或可能不可用)的值时,承诺很有用。 当值可用时-即使是数组或其他复杂值,它也是整个值(而不是其中的一部分)。
您可以在Wikipedia文章中查看更多详细信息和示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.