【问题标题】:await function inside a promise承诺中的 await 函数
【发布时间】:2019-03-20 14:55:54
【问题描述】:

我想在异步函数中创建一个新的 Promise。 在这个 Promise 中,我想调用另一个异步函数,它将调用一些异步内容(从网页中抓取 HTML)。

这是我的代码:

 async extractProductUrlFromHTML(html) {
    const products = html(`h2.product-name`).toArray();
    let extracted = [];
    let promises = [];
    for (let index = 0; index < products.length; index++) {
        const element = products[index];
        let productUrl = element.children[0].attribs.href;
        const productProm = new Promise(async (resolve, reject) => {
            try {               
                console.log("process");
                const product = await this.getProductInfos(productUrl);
                console.log("resolving")
                resolve(product);
            } catch (error) {
                reject(error)
            }

        })
        promises.push(productProm);

    }
    Promise.all(promises).then((prods) => {
        console.log("promises ok", prods)
        extracted.push(prods);
        return (extracted);
    })
}

下面是函数的调用方式:

async scrapeAllProducts({ request, response }) {
    let extractedProducts = []

    //get the html page
    const html = await AxiosService.getHTML('http://www.ubagcollection.com/fr/ubag.html?limit=36')
    const $ = cheerio.load(html);

    let pagesToScrape = await this.extractPagination($);
    pagesToScrape.push(`http://www.ubagcollection.com/fr/ubag.html?limit=36`)

    for (let index = 0; index < pagesToScraep.length; index++) {
        const url = pagesToScrape[index];
        let html = await AxiosService.getHTML(url);
        const $ = cheerio.load(html);
        console.log("start extraction")
        const products = await this.extractProductUrlFromHTML($);
        console.log('product extracted from page :' + index)
        extractedProducts.push(products);
    }
    console.log("all is extracted", extractedProducts)
    ... bla bla bla

我的问题是,在创建所有承诺的那一刻,我可以在程序完成工作之前看到“从页面中提取的产品:...”...

这是我在运行脚本时可以看到的序列:

开始提取 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 过程 从第 1 页提取的产品

每次创建承诺时,我都会记录“进程”,当我的异步函数完成她的工作时,我应该会看到“正在解决”的日志,但这里不是这种情况。

【问题讨论】:

  • 能否在extractProductUrlFromHTML 中的reject(error) 之前添加console.error(error); 以检查是否出现错误?这样做的结果是什么?

标签: javascript node.js cheerio


【解决方案1】:

我认为你可以稍微清理一下你的承诺。您不需要将getProductInfos 包装在一个承诺中。你是await-ing 它,所以我假设它会返回一个承诺。没有必要等待一个承诺,只是将它包装在另一个承诺中并解决它。

也许更像:

async extractProductUrlFromHTML(html) {
  try {
    const products = html(`h2.product-name`).toArray() || [];
    let extracted = [];
    let promises = products.map(element => {
      let productUrl = element.children[0].attribs.href;
      return this.getProductInfos(productUrl); // assuming getProductInfos returns a promise
    });

    const results = await Promise.all(promises); // need to await the Promise.all
    extracted.push(results); // Do you really want to push the array of results into another array? You'll have [[productInfo1, productInfo2, ...]]
    return extracted;
  } catch (e) {
    console.error(e);
  }
}

【讨论】:

    【解决方案2】:

    好的,我解决了我的问题。 我放了一个代码示例,也许它可能对某人有用。

        let extracted = [];
        let promises = [];
        for (let index = 0; index < products.length; index++) {
            const element = products[index];
            let productUrl = element.children[0].attribs.href;
            const productProm = new Promise(async (resolve, reject) => {
                try {
                    await utils.timeout(utils.getRandomInt(1000,4000))
                    const product = await this.getProductInfos(productUrl);
                    resolve(product);
                } catch (error) {
                    reject(error)
                }
    
            })
            promises.push(productProm);
    
        }
        let prods = await Promise.all(promises)
        extracted.push(prods);
    

    【讨论】:

    • 你可能不想这样做。您不需要将这些操作包装在 Promise 中。您可以将 Promise 中的逻辑提取到不同的异步函数。此外,如果您拒绝该 Promise,则在您 await Promise.all(promises) 的部分中没有任何内容可以捕获它,因此您将遇到未捕获的异常。此外,按照您在此处编写代码的方式,它将按顺序处理产品,而不是同时处理,因此需要更长的时间。映射它们可能会更好,将产品数组转换为同时运行的承诺数组。
    猜你喜欢
    • 2021-08-28
    • 1970-01-01
    • 2018-01-05
    • 2016-06-16
    • 1970-01-01
    • 2021-11-27
    • 2016-05-20
    相关资源
    最近更新 更多