JavaScript 异步编程:承诺与生成器
JavaScript asynchronous programming: promises vs generators
Promise 和生成器允许您编写异步代码。我不明白为什么在 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);
但即使有承诺,你也必须以异步方式编写代码 - 你必须始终将回调传递给functions.
编写异步代码比编写同步代码要困难得多。即使有承诺,当代码很大时,也很难看到算法(这是非常主观的,但对于大多数程序员来说,我认为这是真的)。
因此,我们希望以同步方式编写异步代码。这就是发电机来帮助我们的地方.
您可以编写以下代码,而不是上面的代码:
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
技术实现到语言本身中。因此,我们将spawn
替换为async
,yield
替换为await
,并即将进入ES7异步/等待:
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 + <])
什么是最好的:只有回调,或承诺,或带有生成器的承诺 - 这是一个非常主观的问题.
回调是目前最快的解决方案(现在原生承诺的性能非常糟糕)。带有生成器的承诺让您有机会以同步方式编写异步代码。但就目前而言,它们比简单的回调慢得多。
承诺和生成器是不同的软件模式(结构):
- http://en.wikipedia.org/wiki/Futures_and_promises
- http://en.wikipedia.org/wiki/Generator_(computer_programming)
事实上,生成器不是异步的。
当您需要不是一次获取一系列值,而是每个需求获取一个值时,生成器很有用。生成器将在每次调用时立即(同步)返回下一个值,直到它到达序列的末尾(在无限级数的情况下是无穷无尽的)。
当您需要"延迟"值时,承诺很有用,该值可能尚未计算(或可能不可用)。当值可用时 - 它是整个值(不是它的一部分),即使它是一个数组或其他复杂值。
您可以在维基百科文章中查看更多详细信息和示例。
- 为什么同步睡眠功能没有被承诺内异步化
- 如何按照承诺使用mocha/chai/chai测试ES7异步函数
- Node JS异步承诺.所有问题
- 将异步工作流更改为承诺(蓝鸟)
- JQuery 承诺异步对话
- WinJS,从可能是异步的函数返回一个承诺,也可能不是异步的
- 同步异步创建的承诺
- 当我在异步操作Redux上开始单元测试时,没有定义错误承诺
- 使我的异步代码与setTimeout同步.我需要承诺吗
- 异步角度承诺和变量初始化
- 如何在节点中使用承诺一次并行异步多个请求
- 使用链式 Q 承诺异步加载的局部变量
- JavaScript 异步编程:承诺与生成器
- ngInit 不异步工作($q承诺)
- JavaScript ES6 承诺在 while 循环中调用异步操作
- 多个条件异步递归函数和 jQuery 承诺
- JS承诺/异步澄清问题
- 承诺基础知识.如何承诺异步节点代码
- 使用异步.每个都有承诺-异步每个都永不停止
- 使用 Sinon.js 测试承诺/异步流