<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:幾分鐘搞懂異步迭代和生成器

          共 7214字,需瀏覽 15分鐘

           ·

          2021-03-03 22:30

          異步的迭代和生成器

          異步迭代允許我們迭代異步的、按需的數據。比如,當我們通過網絡一塊一塊地下載東西的時候。而異步生成器使它更加方便。

          讓我們先看一個簡單的示例,以掌握語法,然后回顧一個實際的用例。

          回顧迭代

          讓我們回顧一下關于可迭代對象的話題。我們有一個對象,比如range:

          let range = {
            from1,
            to5
          };

          我們想用for..of循環(huán),例如for(value of range),得到1到5的值。換句話說,我們希望向對象添加迭代功能。可以使用名稱Symbol.iterator的特殊方法實現:

          • 當循環(huán)開始時,它應該返回一個帶有下一個方法的對象。

          • 對于每次迭代,都會為下一個值調用next()方法。

          • next()應該以{done: true/false, value:<循環(huán)值>}的形式返回值,其中done:true表示循環(huán)結束。

          以下是可迭代對象范圍的實現:

          let range = {
            from1,
            to5,

            [Symbol.iterator]() { // called once, in the beginning of for..of
              return {
                currentthis.from,
                lastthis.to,

                next() { // called every iteration, to get the next value
                  if (this.current <= this.last) {
                    return { donefalsevaluethis.current++ };
                  } else {
                    return { donetrue };
                  }
                }
              };
            }
          };

          for(let value of range) {
            alert(value); // 1 then 2, then 3, then 4, then 5
          }

          如果有任何不清楚的地方,請訪問Iterables這一章,它提供了關于常規(guī)Iterables的所有細節(jié)。

          異步迭代

          當值異步地出現時,需要異步迭代:在setTimeout或其他類型的延遲之后。

          最常見的情況是對象需要發(fā)出網絡請求來傳遞下一個值,稍后我們將看到一個真實的例子。

          使對象異步可迭代:

          • 使用 Symbol.asyncIterator 代替 Symbol.iterator
          • next()方法應該返回一個承諾(用下一個值來實現)。
          • async關鍵字處理它,我們可以簡單地使用async next()。
          • 要遍歷這樣一個對象,應該使用for await (let item of iterable)循環(huán)。

          作為一個開始的例子,讓我們創(chuàng)建一個可迭代的range對象,類似于前面的對象,但是現在它將異步返回值,每秒返回一個值。

          我們需要做的就是在上面的代碼中執(zhí)行一些替換:

          let range = {
            from1,
            to5,

            [Symbol.asyncIterator]() { // (1)
              return {
                currentthis.from,
                lastthis.to,

                async next() { // (2)

                  // note: we can use "await" inside the async next:
                  await new Promise(resolve => setTimeout(resolve, 1000)); // (3)

                  if (this.current <= this.last) {
                    return { donefalsevaluethis.current++ };
                  } else {
                    return { donetrue };
                  }
                }
              };
            }
          };

          (async () => {

            for await (let value of range) { // (4)
              alert(value); // 1,2,3,4,5
            }

          })()

          正如我們所見,該結構類似于常規(guī)迭代器:

          • 要使一個對象異步可迭代,它必須有一個方法Symbol.asyncIterator(1)。

          • 這個方法必須返回一個對象,next()方法返回一個promise(2)。

          • next()方法不一定是異步的,它可以是一個返回promise的常規(guī)方法,但異步允許我們使用await,所以這很方便。這里我們稍微延遲一下(3)。

          • 為了進行迭代,我們使用for await(let value of range)(4),即在for后添加await。它調用range[Symbol.asyncIterator]()一次,然后調用next()獲取值。

          這里是一個小表格,有不同之處:

          回顧生成器

          現在讓我們回顧一下生成器,因為它們可以使迭代代碼變得更短。大多數時候,當我們想要創(chuàng)建一個可迭代對象時,我們會使用生成器。

          為了簡單起見,省略一些重要的東西,它們是“產生(產生)值的函數”。它們將在章節(jié)生成器中詳細解釋。

          生成器用函數*(注意星號)標記,并使用yield生成一個值,然后我們可以使用for..把它們循環(huán)起來。

          這個例子生成了一個從開始到結束的值序列:

          functiongenerateSequence(start, end{
            for (let i = start; i <= end; i++) {
              yield i;
            }
          }

          for(let value of generateSequence(15)) {
            alert(value); // 1, then 2, then 3, then 4, then 5
          }

          我們已經知道,要使對象可迭代,我們應該添加Symbol.iterator

          let range = {
            from1,
            to5,
            [Symbol.iterator]() {
              return <object with next to make range iterable>
            }
          }

          一種常用的Symbol.iterator返回一個生成器,它使代碼更短,如你所見:

          let range = {
            from1,
            to5,

            *[Symbol.iterator]() { // a shorthand for [Symbol.iterator]: function*()
              for(let value = this.from; value <= this.to; value++) {
                yield value;
              }
            }
          };

          for(let value of range) {
            alert(value); // 1, then 2, then 3, then 4, then 5
          }

          異步生成器

          對于大多數實際應用程序,當我們想要創(chuàng)建一個異步生成一系列值的對象時,我們可以使用異步生成器。

          語法很簡單:將function*async綁定。這使得發(fā)電機是異步的。

          然后使用for await(…)對其進行迭代,如下所示:

          async functiongenerateSequence(start, end{

            for (let i = start; i <= end; i++) {

              // Wow, can use await!
              await new Promise(resolve => setTimeout(resolve, 1000));

              yield i;
            }

          }

          (async () => {

            let generator = generateSequence(15);
            for await (let value of generator) {
              alert(value); // 1, then 2, then 3, then 4, then 5 (with delay between)
            }

          })();

          由于生成器是異步的,我們可以在其中使用await、依賴 Promises、執(zhí)行網絡請求等等。

          異步迭代 range

          常規(guī)生成器可以用作Symbol.iterator,使迭代代碼更短。

          與此類似,異步生成器也可以用作Symbol.asyncIterator來實現異步迭代。

          let range = {
            from1,
            to5,

            // this line is same as [Symbol.asyncIterator]: async function*() {
            async *[Symbol.asyncIterator]() {
              for(let value = this.from; value <= this.to; value++) {

                // make a pause between values, wait for something
                await new Promise(resolve => setTimeout(resolve, 1000));

                yield value;
              }
            }
          };

          (async () => {

            for await (let value of range) {
              alert(value); // 1, then 2, then 3, then 4, then 5
            }

          })();


          瀏覽 60
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩1级黄色片 | 韩国三级无码无遮床戏视频 | www.91AV在线免费观看 | 成人做爰黄AA片免费看三区 | 日本日批视频 |