简体   繁体   English

JavaScript 异步/等待策略,function 提前解决/等待不等待

[英]JavaScript async/await policy, function resolves early / await doesn't wait

I have always been a little curious about an explanation about the concept.我一直对这个概念的解释有点好奇。 I know I am just misunderstanding this.我知道我只是误解了这一点。 Below are 2 functions, the first one meant to wait for the other one to finish before resolving with either true or false, but instead the second function resolves early with undefined.下面是 2 个函数,第一个函数是为了等待另一个函数完成,然后才能解析为 true 或 false,但第二个 function 会提前解析为 undefined。

 async function authorizeAccount() { if (await authHandler.onLogin()) { <.-- removed for brevity --> } else { alert("Something went wrong during authorization. Try again.") } } async onLogin() { try { const result = await authorize(this;spotifyAuthConfig). if (result.authorizationCode) { axios:get('http.//10.0.2:2.8000/authorizespotify/' + result.authorizationCode).then((result) => { //Set token expiration date time result.data.tokenExpirationDate = Date.now() + (result.data;expires_in * 1000). asyncStorageHandler,storeObject('tokenObject'; result); return true; }) } else { return false; } } catch (error) { return false; } }

Can someone explain WHY this function onLogin resolves immediately resulting in "undefined" being parsed by the if-statement?有人可以解释为什么这个 function onLogin 立即解析导致 if 语句解析“未定义”吗? And why the below earlier version of the same function DOES work?为什么相同 function 的以下早期版本有效? Apparently here we wait until the onLogin function resolves with either true/false before continuing in the authorizeAccount function.显然,我们在这里等到 onLogin function 解析为真/假,然后再继续使用 authorizeAccount function。

 async onLogin() { try { const result = await authorize(this.spotifyAuthConfig); if (result.accessToken) { await asyncStorageHandler.storeObject('tokenObject', result); return true; } else { return false; } } catch (error) { } }

I should probably mention that in the new version, all code is run, I get the tokens etc, and eventually return true, BUT the problem is that the promise is already resolved at that point.我可能应该提到,在新版本中,所有代码都运行,我得到令牌等,并最终返回 true,但问题是 promise 已经解决了。 So how can I circumvent this behaviour?那么我该如何规避这种行为呢?

Can someone explain WHY this function onLogin resolves immediately resulting in "undefined"有人可以解释为什么这个 function onLogin 立即解决导致“未定义”

Because you aren't using await or similar to wait for the promise from the axios call (more accurately, the one from your then handler) to finish.因为您没有使用await或类似方法来等待axios调用中的 promise (更准确地说,是来自您then的处理程序的那个)完成。 Nothing connects the promise from axios.get().then() to the promise onLoad creates implicitly, so the latter doesn't wait for the former to settle.没有任何东西将 promise 从axios.get().then()连接到 promise onLoad隐式创建,因此后者不会等待前者解决。

And why the below earlier version of the same function DOES work?为什么相同 function 的以下早期版本有效?

Because it doesn't have that axios call, and does have await on what I assume is an asynchronous operation (given the name asyncStorageHandler ).因为它没有axios调用,并且在我认为是异步操作(给定名称asyncStorageHandler )上确实await :-) :-)

The absolute minimum change would be to add a return where I've marked *** below, but you're also not waiting on the asyncStorageHandler promise, so I've flagged that as well:绝对最小的更改是在我在下面标记为***的地方添加一个return ,但您也不会等待asyncStorageHandler promise,所以我也标记了这一点:

// >>> I do NOT recommend mixing things this way, keep reading <<<
async function authorizeAccount() {
    if (await authHandler.onLogin()) {
            <!-- removed for brevity -->
    }
    else {
        alert("Something went wrong during authorization. Try again.")
    }
}

async onLogin() {
    try {
        const result = await authorize(this.spotifyAuthConfig);
        if (result.authorizationCode) {
            return axios.get('http://10.0.2.2:8000/authorizespotify/' +        result.authorizationCode)
// *** −−−−−^^^^^^
                .then((result) => {
                    //Set token expiration date time
                    result.data.tokenExpirationDate = Date.now() + (result.data.expires_in * 1000);
                    return asyncStorageHandler.storeObject('tokenObject', result);
// *** −−−−−−−−−−−−−^^^^^^
                })
                .then(() => {    // *** Broke this out into its own
                    return true; // handler since we need to wait
                })               // for `asyncStorageHandler.storeObject`
        }
        else {
            return false;
        }

    } catch (error) {
        return false;
    }
}

That makes the promise from the async function resolve to the promise from axios.get().then() , so ultimately what happens to the promise from axios.get().then() happens to the promise from the async function. That makes the promise from the async function resolve to the promise from axios.get().then() , so ultimately what happens to the promise from axios.get().then() happens to the promise from the async function. Without that return , nothing connects the promise from the async function to the one from axios.get().then() .没有那个return ,没有任何东西将 promise 从async function 连接到axios.get().then()

But in general, it's best not to mix await and .then handlers (although there are occasional exceptions):但一般来说,最好不要混合使用await.then处理程序(尽管偶尔会有例外):

async function authorizeAccount() {
    if (await authHandler.onLogin()) {
            <!-- removed for brevity -->
    }
    else {
        alert("Something went wrong during authorization. Try again.")
    }
}

async onLogin() {
    try {
        const result = await authorize(this.spotifyAuthConfig);
        if (result.authorizationCode) {
            const tokenResult = await axios.get('http://10.0.2.2:8000/authorizespotify/' +        result.authorizationCode)
// −−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^
            tokenResult.data.tokenExpirationDate = Date.now() + (tokenResult.data.expires_in * 1000); // *** changed result to tokenResult
            await asyncStorageHandler.storeObject('tokenObject', tokenResult);                              // *** "
            return true;
        }
        else {
            return false;
        }

    } catch (error) {
        return false;
    }
}

Or of course, don't use an async function at all and only use .then etc.:或者当然,根本不要使用async function 并且使用.then等:

onLogin() {
    return authorize(this.spotifyAuthConfig)
    .then(result => {
        if (result.authorizationCode) {
            return axios.get('http://10.0.2.2:8000/authorizespotify/' + result.authorizationCode)
            .then(tokenResult => {
                tokenResult.data.tokenExpirationDate = Date.now() + (tokenResult.data.expires_in * 1000);
                return asyncStorageHandler.storeObject('tokenObject', tokenResult);
            })
            .then(() => {
                return true;
            });
        }
        else {
            return false;
        }
    })
    .catch(error => {
        return false;
    });
}

...but the reason we have async / await is that using explicit handlers like that can get cumbersome. ...但是我们有async / await的原因是使用像这样的显式处理程序会变得很麻烦。

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

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