【问题标题】:Async sometimes returning undefined异步有时返回未定义
【发布时间】:2020-09-05 06:47:16
【问题描述】:

调用以下方法时:

getLyrics: async function(song) {
    const body = await this.getSongBody(song);
    const lyrics = await cheerio.text(body('.lyrics'));
    return lyrics;
} 

这样:

genius.getLyrics('What a wonderful')
    .then((res) => console.log(res))
    .catch((err) => console.log(err.message));

一切正常,Louise Armstrong 的“What a wonderful world”歌词在控制台中弹出。

但是,当我运行相同的代码但在“cheerio.text...”前面没有“等待”时,有时会生成歌词,而有时会在控制台中显示“未定义”。现在让我摸不着头脑的是“cheerio.text ...”不会返回承诺(尽管“getSongBody”会),所以据我了解,没有必要“等待”它完成。

我显然遗漏了一些关于 async/await 的内容,但不知道是什么。任何帮助将不胜感激!

谢谢

编辑:添加了一个可重现的示例,如下所示:

const fetch = require('node-fetch');
const cheerio = require('cheerio');


// API
function geniusApi(token) {
    this._token = token;
    this._auth = {'Authorization': 'Bearer ' + this._token};
};

geniusApi.prototype = {  
    getSongURL : async function(search_keyword){
        const res = await fetch('https://api.genius.com/search?q=' + 
                                 search_keyword,{headers: this._auth});
        const body = await res.text();
        const body_parsed = JSON.parse(body);

        if (body_parsed.response.hits.length == 0){
            console.log('No such song found');
            throw Error('No such song found');
        } 

        const url = body_parsed.response.hits[0].result.url;
        return url;
    },

    getSongBody: async function (song){
        const url = await this.getSongURL(song);
        const response = await fetch(url);
        const body = await response.text();
        const body_parsed = cheerio.load(body);
        return body_parsed;
    },

    getLyrics: async function(song) {
        const body = await this.getSongBody(song);
        const lyrics = cheerio.text(body('.lyrics'));
        return lyrics;
    }
}

// TEST EXAMPLE
const token = 
'OTh1EYlsNdO1kELVwcevqLPtsgq3FrxfShIXg_w0EaEd8CHZrJWbWvN8Be773Cyr';
const genius = new geniusApi(token);

genius.getLyrics('What a wonderful')
    .then((res) => console.log(res))
    .catch((err) => console.log(err.message));

【问题讨论】:

  • 添加了可重现的示例,有时它会打印歌词,有时它不会打印任何东西。令牌是暂时添加的,因为我怀疑有人会费心费力地获得自己的令牌。
  • cheerio.load 返回什么?一个函数?
  • @Bergi 它返回一个类似 jQuery 的对象,用于在已解析的 DOM 上进行选择
  • @Bucket 不,当试图将任何一个视为承诺时,我得到类似“TypeError: body(...).then is not a function”。

标签: javascript node.js async-await es6-promise cheerio


【解决方案1】:

对于任何偶然发现相同问题的人来说,本例中的问题与 async、promise 或任何其他 JS 特性无关。代码在使用 async 时可以正常运行只是一个巧合,后来发现它并不总是使用 async。

原因很简单,我用来获取数据的 Genius API 会针对相同的 API 查询返回不同的源代码。

返回了两个不同的源代码,一个包含一个名为“lyrics”的 div,而另一个则没有。因此,有时歌词是用cheerio找到的,有时却不是。

【讨论】:

    猜你喜欢
    • 2020-09-05
    • 1970-01-01
    • 2018-09-22
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多