promise 和生成器允许您编写异步代码.我不明白为什么ECMA脚本6中引入了这两种机制.什么时候最好使用promise ,什么时候使用发电机?
promise 和生成器允许您编写异步代码.我不明白为什么ECMA脚本6中引入了这两种机制.什么时候最好使用promise ,什么时候使用发电机?
这两种技术之间没有对立:它们共存,相辅相成.
Promises allows you to get the result of an asynchronous operation which is not available yet.
It solves the Pyramid of Doom problem. So instead of:
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);
But even with promises you must write code in asynchronous fashion - you must always pass callbacks to the functions.
Writing asynchronous code is much harder than synchronous. Even with promises, when the code is huge, it becomes difficult to see the algorithm (it's very subjective, but for the majority of programmers I think it's true).
So we want to write asynchronous code in synchronous fashion. That's where generators are coming to help us.
Instead of the code above 你可以写:
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}
的结果)一定是一个promise .你不能用回调来做这件事.
剩下要做的是将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;
}
I recommend you to watch this video to understand more this and some other coming techniques.
Hint: If the guy speaks too fast for you, slow down the speed of playing ("settings" in right bottom corner, or just push [shift + <])
What is the best: only callbacks, or promises, or promises with generators - this is a very subjective question.
Callbacks is the fastest solution possible at this time (performance of native promises are very bad now). Promises with generators give you opportunity to write asynchronous code in synchronous fashion. But for now they are much slower than simple callbacks.