簡體   English   中英

帶有異步返回 Promise 的映射

[英]Map with async returns Promise

下面的代碼正在返回[Promise, Promise, Promise, Promise, Promise]並且我不確定我在這里做錯了什么。 我在這個異步函數中缺少什么?

 async function testFunction(page) {

  async function multipleTests(test) {
    const tests = Array.from(test.querySelectorAll("li"));

    const allTests = tests.map((test, index) => {
      return {
        title: test.querySelector("h3").innerText
      };
    });
    return allTests;
  }


    const tests = Array.from(document.querySelectorAll("section.test")).map(async test => {
      if (test.querySelector("ul li")) {
        const tests = await multipleTests(test);
        return tests;
      }
    })

    console.log(tests);

}

首先,假設這是正常的瀏覽器代碼,我在函數的.map()部分根本看不到任何異步內容。 所以,你不應該在那里使用async

其次,所有異步函數都返回一個承諾。 所以當你這樣做時:

const allTests = test.map(async () => {...});

你總是會得到一系列的承諾。 如果你想從這些承諾中獲取值,你必須使用Promise.all()如下所示:

const allTests = Promise.all(test.map(async () => {...});)

但是,如果.map()回調中沒有任何內容是異步的,那么這里根本不需要承諾或async - 從.map()完全刪除async

const allTests = test.map(() => {...});

然后,第二個.map()中的第三個,看起來一切都是同步的。 我認為您可以像這樣將所有代碼簡化為同步:

function testFunction(page) {

    function multipleTests(test) {
        const tests = Array.from(test.querySelectorAll("li"));

        const allTests = tests.map((test, index) => {
            return {
                title: test.querySelector("h3").innerText
            };
        });
        return allTests;
    }


    const tests = Array.from(document.querySelectorAll("section.test")).map(test => {
        if (test.querySelector("ul li")) {
            return multipleTests(test);
        } else {
            // return something else here or your tests array will have an undefined value
        }
    })

    console.log(tests);

}

一些需要考慮的建議:

  1. 不要通過在純同步代碼段中使用asyncawait或 promises 來使事情復雜化。 雖然async/await可以幫助人們更輕松地編寫異步代碼,但您仍然需要處理 Promise 並使用await或最終使用.then()獲取所有結果,而同步代碼只能直接返回或計算一個值。
  2. 所有async函數都返回一個承諾。 總是。 調用代碼必須對返回的承諾使用await.then()才能訪問該值。
  3. .map() (包含所有數組迭代器方法)不是async或 promise saavy。 所以,當你為.map()聲明一個async回調時,回調總是返回一個承諾,所以你總是得到一個承諾數組。 有時這很有用並且需要什么,但是您將不得不使用Promise.all()類的東西來了解所有這些承諾何時已解決以及何時可以獲得它們的所有值。
  4. 很多時候,對於異步代碼,在普通的for循環中使用asyncawait更簡單,因為在 ES6 中開始的for構造是await saavy 並且它會暫停循環以await使您的代碼更易於編寫。
  5. 您在函數第二部分中的tests計算看起來像是奇怪的邏輯。 您首先執行document.querySelectorAll("section.test")然后再次查找test.querySelector("ul li") 看起來你可以只做一個選擇器最初document.querySelectorAll("section.test ul li")並避免兩個單獨的操作。

暫無
暫無

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

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