【问题标题】:Refactoring async functions in javascript在 javascript 中重构异步函数
【发布时间】:2020-03-17 08:36:14
【问题描述】:

我写了一个程序,分三步提取下载照片的链接:

  1. getPersons() 函数获取要遍历的人员的完整列表。
  2. 从人员列表中获取照片下载链接。
  3. 从步骤 2 中创建的列表下载。

我正在尝试将第 2 步重构为异步函数。 有没有一种简单的方法可以将第二步重构为函数以使代码更具可读性?

理想情况下,我想检索所有链接,然后才开始下载。

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

【问题讨论】:

  • 你可以使用 Promise.all(异步方法)。

标签: javascript node.js async-await axios


【解决方案1】:

我会这样重构它。删除匿名函数上的 .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();

【讨论】:

    【解决方案2】:

    您几乎无法从异步性中获得太多好处,因为您最终会发出串行请求。我会这样写(未经测试):

    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");
        // ...
      });
    }
    

    【讨论】:

    • 谢谢。我会试试的。
    猜你喜欢
    • 2014-10-28
    • 1970-01-01
    • 2015-03-29
    • 1970-01-01
    • 2021-12-28
    • 2017-08-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多