简体   繁体   English

异步函数内的异步函数返回未定义的值

[英]Async function inside an async function returns undefined value

I'm working in a JS class and I can't figure out the reason why colors.ColorCheck(0).ColorCode and colors.ColorCheck(0).Color return undefined values.我在一个 JS 类中工作,我无法弄清楚为什么colors.ColorCheck(0).ColorCodecolors.ColorCheck(0).Color返回undefined值。

As you can see, "0" is passed as an argument of the function ColorCheck and is used inside the functions this.ColorCode and this.Color .如您所见,“0”作为函数ColorCheck的参数传递,并在函数this.ColorCodethis.Color

I'm pretty sure I'm missing something in declaring the two functions ( this.ColorCode and this.Color ) inside the main function ( ColorCheck ), but I can't see what.我很确定我在主函数( ColorCheck )中声明两个函数( this.ColorCodethis.Color )时遗漏了一些东西,但我看不出是什么。

I'm a newbie in JS, so I wouldn't be surprised if the solution seems evident for you guys.我是 JS 的新手,所以如果解决方案对你们来说很明显,我不会感到惊讶。

class Colors {

    constructor(){}

    async ColorCheck(ID){
        this.ColorCode = (async()=>{
            this.info = await axios.get ('https://.../${ID}.json')
            this.CodeC = this.info.map(t=>t.colorcode)
            return this.CodeC
        })
        this.Color = (async()=>{
            this.info = await axios.get ('https://.../${ID}.json')
            this.C = this.info.map(t=>t.color)
            return this.C
        })
    }
}

const colors = new Colors()
colors.ColorCheck(0).ColorCode
colors.ColorCheck(0).Color

Your ColorCheck function is not returning anything, so when calling it as colors.ColorCheck(0) , that's returning undefined .您的ColorCheck函数没有返回任何内容,因此当将其调用为colors.ColorCheck(0) ,将返回undefined

I think rather than setting this.ColorCode and this.Color , with this referring to the Color instance, what you actually want is to return an object with two keys, ColorCode and Color , whose values are two curried async functions that will make a GET request with the provided id when called.我想,而不是设置this.ColorCodethis.Color ,与this指的是Color的实例,你真正想要的是有两个键,返回一个对象ColorCodeColor ,其值是两个咖喱异步功能,这将使一个GET调用时使用提供的id请求。

That would probably look something like this:那可能看起来像这样:

 // Just mocking axios for this example: const axios = { get: (url) => new Promise((resolve, reject) => { console.log(`Making a request to ${ url }...`); setTimeout(() => { resolve([{ colorCode: '#F00', color: 'red', }, { colorCode: '#0F0', color: 'green', }, { colorCode: '#00F', color: 'blue', }]); }, 2000); }), }; class Colors { constructor() { } ColorCode(id) { return { ColorCode: (async () => { const info = await axios.get(`https://.../${ id }.json`); return info.map(t => t.colorCode); }), Color: (async () => { const info = await axios.get(`https://.../${ id }.json`); return info.map(t => t.color); }), }; } } const colors = new Colors(); const returnedValue = colors.ColorCode(0); (async () => { console.log((await returnedValue.ColorCode()).join(', ')); console.log((await returnedValue.Color()).join(', ')); })();
 .as-console-wrapper { max-height: none !important; }

You could also move the axios call to the ColorCode function (without making it async ) so that you don't make an additional request every time any of the two returned functions are called:您还可以将 axios 调用移动到ColorCode函数(不使其成为async ),以便每次调用两个返回的函数中的任何一个时都不会发出额外的请求:

 // Just mocking axios for this example: const axios = { get: (url) => new Promise((resolve, reject) => { console.log(`Making a request to ${ url }...`); setTimeout(() => { resolve([{ colorCode: '#F00', color: 'red', }, { colorCode: '#0F0', color: 'green', }, { colorCode: '#00F', color: 'blue', }]); }, 2000); }), }; class Colors { constructor() { } ColorCode(id) { // Note there no `await` here: const infoPromise = axios.get(`https://.../${ id }.json`); return { ColorCode: (async () => { return (await infoPromise).map(t => t.colorCode); }), Color: (async () => { return (await infoPromise).map(t => t.color); }), }; } } const colors = new Colors(); const returnedValue = colors.ColorCode(0); (async () => { console.log((await returnedValue.ColorCode()).join(', ')); console.log((await returnedValue.Color()).join(', ')); })();
 .as-console-wrapper { max-height: none !important; }

welcome!欢迎! just remember to await or then the host async function as well只记得awaitthen主机异步功能

example:例子:

async function a() {
  return await http.get(...)
}
a() // undefined (promise awaiting resolve)
await a(); // expected value
a().then(value => console.log(value)) // expected value

in case of function a() , you can just return the async task itself, which you will have to resolve later anyway:function a()情况下,您可以只返回异步任务本身,无论如何您都必须稍后解决:

function a() {
  return http.get(...)
}

a() // undefined (promise awaiting resolve)
await a() // expected value
a().then(...) // expected value

also: - you assigned this.ColorCode to be a(n async) function, which means you will have to call it in order to get value retuned to it:还: - 您将this.ColorCode指定为 (n async) 函数,这意味着您必须调用它才能将值重新调整到它:

await Colors.ColorCheck('0'); // Colors.ColorCode and Colors.Color are now being assigned
await Colors.ColorCode(); // this.CodeC is being assigned to the class Colors + returned. which means from now on Colors.CodeC is also accessible
await Colors.Color() // assigns Colors.C a value + returns it. from now on Colors.C is also accessible

note that Colors.info is also assigned and overridden each time you call any of the functions (Colors.ColorCode / Colors.Color)

  • the this keyword is most likely misused: refer to this article in MDN. this关键字最有可能被误用:请参阅 MDN 中的这篇文章。 currently your values are stored within the class Colors context, instead of probably just storing them in the function's context, using const .当前,您的值存储在class Colors上下文中,而不是可能只是使用const将它们存储在函数的上下文中。 eg:例如:
const info = await axios...
const c = info.map(...);
return c;

You want to use string literals , but you are defining as a normal string:您想使用字符串文字,但您定义为普通字符串:

this.info = await axios.get ('https://.../${ID}.json');

You should change to this:你应该改成这样:

this.info = await axios.get (`https://.../${ID}.json`);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM