异步有时返回未定义
Async sometimes returning undefined
调用以下方法时:
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..." 前面没有 "await" 时,有时会生成歌词,而有时 "undefined" 会出现在控制台中.现在让我摸不着头脑的是 "cheerio.text..." 不是 return 承诺(尽管 "getSongBody" 是),所以据我了解,没有必要 "wait" 让它完成。
我显然遗漏了一些关于 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));
对于任何偶然发现相同问题的人来说,本例中的问题与异步、promise 或任何其他 JS 功能无关。代码在使用 async 时运行正常只是一个巧合,后来发现它并不总是与 async 一起工作。
原因很简单,我用来获取数据的 Genius API 会 return 不同的源代码对于相同的 API 个查询。
两个不同的源代码被 returned,一个包含一个 div 称为“歌词”而另一个没有。因此,有时歌词是使用 cheerio 找到的,有时则不是。
调用以下方法时:
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..." 前面没有 "await" 时,有时会生成歌词,而有时 "undefined" 会出现在控制台中.现在让我摸不着头脑的是 "cheerio.text..." 不是 return 承诺(尽管 "getSongBody" 是),所以据我了解,没有必要 "wait" 让它完成。
我显然遗漏了一些关于 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));
对于任何偶然发现相同问题的人来说,本例中的问题与异步、promise 或任何其他 JS 功能无关。代码在使用 async 时运行正常只是一个巧合,后来发现它并不总是与 async 一起工作。
原因很简单,我用来获取数据的 Genius API 会 return 不同的源代码对于相同的 API 个查询。
两个不同的源代码被 returned,一个包含一个 div 称为“歌词”而另一个没有。因此,有时歌词是使用 cheerio 找到的,有时则不是。