【问题标题】:How to wait for the internal process of a function to execute completely before returning?如何等待函数内部进程执行完毕再返回?
【发布时间】:2020-04-07 13:50:36
【问题描述】:

我正在尝试使用 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。

注意:fetchF() 返回 true 后,所有deepF() 函数稍后执行缓慢

如何等待fetchF() 执行所有内部deepF(),然后在fetchF() 中返回true?

【问题讨论】:

    标签: reactjs promise callback cheerio asynchronous-javascript


    【解决方案1】:

    更改fetchF() 的实现以正确返回链接到所有ajax 调用的promise。将 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() 成为一个函数,该函数返回一个仅当其中的所有axios.get() 调用完成并使用true 值解析时才解析的函数。如果有任何错误,它会捕获这些错误并使用 false 值解决(这似乎是您想要的逻辑,尽管不只是让被拒绝的 Promise 传播并在更高级别捕获它以表示有点不寻常错误)。

    然后,你可以使用:

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

    然后,fReturn 将是 truefalse


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

    【讨论】:

      猜你喜欢
      • 2019-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多