JavaScript 异步编程:promise 与生成器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28031289/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 08:18:29  来源:igfitidea点击:

JavaScript asynchronous programming: promises vs generators

javascriptnode.jsasynchronouspromiseecmascript-6

提问by sribin

Promises and generators allow you to write asynchronous code. I do not understand why both of these mechanisms are introduced in ECMA script 6. When is it best to use the promises, and when the generators?

Promises 和 generators 允许你编写异步代码。我不明白为什么在 ECMA 脚本 6 中引入了这两种机制。什么时候最好使用 promise,什么时候使用生成器?

回答by alexpods

There is no opposition between these two techniques. They coexist together complementing each other nicely. Promises give you capability to get result of an asynchronous operation which does not available yet. It solves Pyramid of Doomproblem. So instead of:

这两种技术之间没有对立。它们共存在一起,相得益彰。Promise 使您能够获得尚不可用的异步操作的结果。它解决了厄运金字塔问题。所以而不是:

function ourImportantFunction(callback) {
  //... some code 1
  task1(function(val1) {
    //... some code 2
    task2(val1, function(val2) {
      //... some code 3
      task3(val2, callback);
    });
  });
}

you can write:

你可以写:

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 then synchronous. Even with promises when the code is huge it becomes difficult to see the algorithm (well, it's very subjective, someone can argue with it. But for 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. So instead of code above you can write:

但即使有 Promise,您也必须以异步方式编写代码 - 您必须始终将回调传递给函数。编写异步代码比同步要困难得多。即使在代码很大时有承诺,也很难看到算法(嗯,这是非常主观的,有人可以与之争论。但对于大多数程序员来说,我认为这是真的)。所以我们想以同步方式编写异步代码。这就是发电机来帮助我们的地方。因此,您可以编写以下代码来代替上面的代码:

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);

where simplest possible spawnrealization can be something like:

最简单的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
    });
  };
}

As you can see value(result of some asynchronous function task{N}) must be a promise. You can't do this with callbacks.

如您所见value(某些异步函数的结果task{N})必须是一个承诺。你不能用回调来做到这一点。

What remains to do is to implement spawntechnique into language itself. So we are replacing spawnwith asyncand yieldwith awaitand are coming to ES7 async/await:

剩下要做的是将spawn技术应用到语言本身中。因此,我们正在取代spawnasyncyieldawait,并即将ES7异步/ 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 videoto more understand this and some other coming techniques. If the guy speaks too fast for you, slow down the speed of playing ("settings" in right bottom corner, or just push [shift+ <])

我建议您观看此视频以更深入地了解这一点以及其他一些即将推出的技术。如果对方对你说的太快,放慢播放速度(右下角的“设置”,或者直接按[ shift+ <])

What is the best: just callbacks, or promises, or promises with generators - this is 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 much slower then simple callbacks.

什么是最好的:只是回调,或承诺,或与生成器的承诺 - 这是一个非常主观的问题。回调是目前最快的解决方案(现在原生 Promise 的性能非常糟糕)。带有生成器的 Promise 使您有机会以同步方式编写异步代码。但是现在它们比简单的回调慢得多。

回答by Ivan Samygin

Promises and Generators are different software patterns (constructs):

Promises 和 Generators 是不同的软件模式(构造):

  1. http://en.wikipedia.org/wiki/Futures_and_promises
  2. http://en.wikipedia.org/wiki/Generator_(computer_programming)
  1. http://en.wikipedia.org/wiki/Futures_and_promises
  2. http://en.wikipedia.org/wiki/Generator_(computer_programming)

In fact, generators aren't asynchronous.

事实上,生成器不是异步的。

Generators are useful when you need to get a series of values not at once, but one per demand. Generator will return next value immediately (synchronously) on every call until it reaches the end of the sequence (or endless in case of infinite series).

当您需要不是一次获得一系列值而是每个需求一个值时,生成器很有用。Generator 将在每次调用时立即(同步)返回下一个值,直到它到达序列的末尾(或者在无限序列的情况下是无穷无尽的)。

Promises are useful when you need to "defer" the value, that may not be computed (or may not be available) yet. When the value is available - it's the whole value (not part of it) even it is an array or other complex value.

当您需要“延迟”可能尚未计算(或可能不可用)的值时,Promise 很有用。当值可用时 - 它是整个值(不是它的一部分),即使它是一个数组或其他复杂值。

You can see more details and examples in wikipedia articles.

您可以在维基百科文章中查看更多详细信息和示例。