簡體   English   中英

JavaScript異步編程:Promise vs生成器

[英]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是不同的軟件模式(構造):

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

實際上,生成器不是異步的。

當您需要一次獲取一系列值而不是每個需求一個值時,生成器很有用。 生成器將在每次調用時立即(同步)返回下一個值,直到到達序列的末尾(如果是無限序列,則返回無窮)。

當您需要“推遲”可能尚未計算(或可能不可用)的值時,承諾很有用。 當值可用時-即使是數組或其他復雜值,它也是整個值(而不是其中的一部分)。

您可以在Wikipedia文章中查看更多詳細信息和示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM