簡體   English   中英

重構 javascript 中的異步函數

[英]Refactoring async functions in javascript

我編寫了一個程序來提取鏈接以通過三個步驟下載照片:

  1. getPersons() function 獲取要遍歷的人員的完整列表。
  2. 從人員列表中獲取照片下載鏈接。
  3. 從步驟 2 中創建的列表下載。

我正在嘗試將第 2 步重構為異步 function。 有沒有一種簡單的方法可以將第二步重構為 function 以使代碼更具可讀性?

理想情況下,我想檢索所有鏈接,然后才開始下載。

const axios = require("axios");
const cheerio = require("cheerio");

const url = "https://www.website.com";

const persons = [];

async function getPersons() {
  await axios.get(url).then(response => {
    const html = response.data;
    const $ = cheerio.load(html);
    const personList = $(".bio-btn");
    console.log(personList.length);

    personList.each(function() {
      const link_raw = $(this).attr("href");

      const link = url + link_raw;
      const name = link_raw.replace("/bio/", "");

      person.push({
        name,
        link
      });
    });
  });
}

getPersons().then(function() {
  persons.forEach(async function(person) {
    var personLink = person.link;
    await axios.get(personLink).then(response => {
      const html = response.data;
      const $ = cheerio.load(html);
      const snapshots = $(".ratio-4-3");
      snapshots.each(function() {
        const pic = $(this).attr("style");
        if (pic != undefined && pic.includes("biopicture")) {
          var bioPhoto = s[1];
        }
      });
    });
  });
});

由於您最終會發出串行請求,因此您幾乎不會從異步性中獲得太多好處。 我會這樣寫(未經測試):

async function getPersons() {
  const response = await axios.get(url);
  const html = response.data;
  const $ = cheerio.load(html);
  const personList = $('.bio-btn');

  const persons = [];
  personList.each(function() {
    const link_raw = $(this).attr('href');

    const link = url + link_raw;
    const name = link_raw.replace("/bio/", "");

    persons.push({
      name,
      link,
    });
  });
  return persons;
};

async function getSnapshots() {
  const persons = await getPersons();
  const linkPromises = persons.map(person => axios.get(person.link));
  const linkResponses = await Promise.all(linkPromises);
  linkResults.forEach(response => {
    const html = response.data;
    const $ = cheerio.load(html);
    const snapshots = $(".ratio-4-3");
    // ...
  });
}

我會像這樣重構它。 刪除匿名函數上的 .then .then()方法和function關鍵字使代碼看起來更干凈。
使用Promise.all()可以讓您異步啟動所有下載,這比一張一張下載圖像要好。

const axios = require('axios');
const cheerio = require('cheerio');

const url = 'https://www.website.com';


async function getPersons() {
  const response = await axios.get(url);
  return extractPersonList(response);
}

// Step 1
function extractPersonList(response) {
  const persons = [];
  const html = response.data;
  const $ = cheerio.load(html);
  const personList = $('.bio-btn');
  console.log(personList.length);
  personList.each(() => {
    const link_raw = $(this).attr('href');
    const link = url + link_raw;
    const name = link_raw.replace('/bio/', '');
    persons.push({
      name,
      link
    });
  });
  return persons;
}

async function getPhotos() {
  const persons = await getPersons();
  const promisies = persons.map(p => axios.get(p.link));
  // Step 2
  const responses = await Promise.all(promisies);

  // Step 3
  responses.forEach(response => {
    const html = response.data;
    const $ = cheerio.load(html);
    const snapshots = $('.ratio-4-3');
    snapshots.each(() => {
      const pic = $(this).attr('style');
      if (pic && pic.includes('biopicture')) {
        var bioPhoto = s[1];
      }
    });
  });
}

// Call getPhotos to start the process
getPhotos();

暫無
暫無

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

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