简体   繁体   中英

Async await strange behaviour with functions

I have following asynchronous code example:

// Functions

function getSomePromise() {
    let a = new Promise((resolve, reject) => {    
        setTimeout(function(){
            console.log("Inside promise...");
            resolve("Success!"); 
        }, 1000);
    });

    return a;
}

async function someWrapper(i) {
    console.log('A: '+ i);
    await getSomePromise();
    console.log('B: ' + i);    
}

And two tests:

async function test1() {
    for(let i=0; i<5; i++) {
        // body copy-pasted of someWrapper function:
        console.log('A: '+ i);
        await getSomePromise();
        console.log('B: ' + i);
    }    
}

async function test2() {
    for(let i=0; i<5; i++) {
        someWrapper(i);                
    }    
}

And here are results in chrome console after run separatley test1() and test2() :

Test 1               |      Test 2
---------------------------------------------
A: 0                 |      A: 0
Inside promise...    |      A: 1
B: 0                 |      A: 2
A: 1                 |      A: 3
Inside promise...    |      A: 4
B: 1                 |      Inside promise...
A: 2                 |      B: 0
Inside promise...    |      Inside promise...
B: 2                 |      B: 1
A: 3                 |      Inside promise...
Inside promise...    |      B: 2
B: 3                 |      Inside promise...
A: 4                 |      B: 3
Inside promise...    |      Inside promise...
B: 4                 |      B: 4

Question: Why when we use function someWrapper() in for-loop (test2) we get different result than wen we copy-paste this function body directly into for-loop (test1) ?

(above example is quite abstract, however "I found this behaviour" on calling ajax requests (instead console.log('A: '+ i); and console.log('B: '+ i); ) which sequence are very important in my app (request A1 must be before request B0 ...) )

test2:

your test2 is not async until you make it async. You've wrote synchronous code inside test2.they are the console.log. Only async code inside test2 is call to promise.Let's break it down

async function test2() {
    for(let i=0; i<5; i++) {
        someWrapper(i);                
    }    
}

above code fires someWrapper() 5 times sequentially.so it write the first sync code which is console.log('A'+i) 5 times in a row in console.

then each someWrapper() waits for async promise to return parallelly .after each promise resolved it prints 'Inside promise'. until the promise resolves, the execution halts and can not proceed to next step

then, after resolving the promise, it prints out the second sync code which is console.log('B'+i) in console

test1:

test1 will behave differently than test2.Let's break it down

async function test1() {
    for(let i=0; i<5; i++) {
        // body copy-pasted of someWrapper function:
        console.log('A: '+ i);
        await getSomePromise();
        console.log('B: ' + i);
    }    
}

the main distinction is you are awaiting inside for loop . So this will literally pause the loop which was not the case for test1

so for each iteration it will print console.log('A'+i)

then pause the iteration for await getSomePromise()

when the promise return will print 'Inside Promise'

then print console.log('B'+i)

then continue next iteration.

Looking at the comments

@HMR - hm... I not understand - in question example there is async function someWrapper() but that function don't return anything (it even doesn't have return statement (!) ) - can you explain what do you mean by async functions immediately return a promise ? - Kamil Kielczewski

it seems you don't understand the async await. I usually advice people to lay off await until you understand promises. However in next comment under question I give you the answer:

someWrapper will immediately return a promise that resolves to undefined. The await only "waits" in the someWrapper function but the function calling someWrapper will immediately receive a promise that resolves in undefined. Functions always return something, if you don't in code then it will return undefined. If it's an async function without a return then it'll return a promise that resolves in undefined - HMR.

Await is syntax sugar (nicer looking code) for promises and doesn't actually wait for anything.

Maybe the following code clears things up:

 var test = async () => { await 22;//doesn't even matter if value is promise console.log("after wait"); } var result = test(); console.log("outside test we don't wait for anything",result); 

If you don't understand why the output of that code is:

outside test we don't wait for anything Promise {< pending >}

after wait

Then I'd advice you to use just promises, until you do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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