0

我正在尝试使用axiosCheerio获取网页,但我无法检索所有数据,因为即使在内部过程完全完成之前,函数也会返回。我正在使用 ReactJS,当我单击页面中的按钮时,会调用此函数:

analyse = async(e) => {

      this.a = await axios.get('xxx');
      this.s = await axios.get('yyy');
      this.f = await axios.get('zzz');

      let aReturn = this.fetchA(this.a.data);

      let sReturn = this.fetchS(this.s.data);

      let fReturn = this.fetchF(this.f.data);

      if(await fReturn === true && await aReturn === true && await sReturn === true){
            anotherFunction();
      }
}

在上面的代码中,axios 工作正常,函数fetchA()和函数fetchS()都是简单的函数,没有任何进一步的内部函数调用:

fetchA(html){
    const $ = cheerio.load(html);

    //some process

    return true;
}

fetchS(html){
    const $ = cheerio.load(html);

    //some process

    return true;
}

未完全执行而返回的函数是fetchF()

fetchF(html){
    const $ = cheerio.load(html);

    $('div._someClassName').children().each((i,elem) => {

    let link = $(elem).find('a').first().attr('href');

    axios.get(link)
    .then(response => {

        this.deepF(response.data);
    })
    .catch(err => {
        console.log("Error : ",err);
     })

    };
    return true;
}

在上面的函数中,每个孩子都有一个唯一的链接,我需要axios.get()再次调用另一个函数deepF()来获取该页面的数据。内部函数deepF又是一个小函数:

deepF(html){
    const $ = cheerio.load(html);

    //some process

    return true;
}

在整个代码中,在内部fetchF()没有完全执行所有deepF()函数的情况下返回 true。

注意:所有函数在返回 truedeepF()后会慢慢执行fetchF()

在返回 true 之前,我如何等待fetchF()执行所有内部?deepF()fetchF()

4

1 回答 1

1

更改实现fetchF()以正确返回链接到所有 ajax 调用的承诺。将 ajax 承诺累积到一个数组中,然后用于Promise.all()知道它们何时全部完成。然后,您可以await得到该函数的结果。

从此改变:

fetchF(html){
    const $ = cheerio.load(html);

    $('div._someClassName').children().each((i,elem) => {

    let link = $(elem).find('a').first().attr('href');

    axios.get(link)
    .then(response => {

        this.deepF(response.data);
    })
    .catch(err => {
        console.log("Error : ",err);
     })

    };
    return true;
}

对此:

fetchF(html){
    const $ = cheerio.load(html);
    const promises = [];
    $('div._someClassName').children().each((i,elem) => {

        let link = $(elem).find('a').first().attr('href');

        promises.push(axios.get(link).then(response => {
            return this.deepF(response.data);
        }).catch(err => {
            console.log("Error : ",err);
            throw err;
        }));
    });
    return Promise.all(promises).then(() => true).catch(() => false);
}

这形成了一个函数,该函数返回一个仅在其中的所有调用完成并使用值fetchF()解析时才解析的 Promise 。如果有任何错误,它会捕获这些错误并使用一个值解决(这似乎是您想要的逻辑,尽管不只是让被拒绝的 Promise 传播并在更高级别捕获它以表示错误有点不寻常)。axios.get()truefalse

然后,您可以使用:

let fReturn = await this.fetchF(this.f.data);

并且,然后fReturn将是trueor false


如果您的任何其他函数中有异步操作,它们还需要返回一个直接链接到您的异步操作的 Promise。

于 2019-12-14T09:54:19.503 回答