了解javascript promises和异步/等待运行同步代码

时间:2019-10-30 22:51:25

标签: javascript node.js asynchronous promise async-await

我已经在StackOverflow上发布了有关此主题的问题。按照建议,我试图简化我的问题。

  

尽管我已经阅读并尝试了不同的方法,但我不知道如何使用Promises及其新的精巧版本使用async / await进行同步代码。

在这里,我链接了有关该主题的一些很好的文档,以防将来对人们有所帮助。基本上,Promise是对回调地狱的一种回答,是一种使代码在其他代码执行后执行的方法,这使事情同步发生,因为JavaScript(因此Node.js)本质上是异步的。 Async / await建立在Promises之上,可以简化代码。

understanding JavaScript Promises

modern JavaScript with async/await

Async/await explained with examples

why moving from Promises to async/await

尽管我似乎了解这个概念,但是我无法解释我获得的结果。为了更好地理解,下面是一个使用node.js -v v8.10.0

的测试文件
/* This file try to use Promises and async/await to run code synchronously */

/* declaration of some Promisified functions */
const doSomethingAsync = () => {                                    // direct declaration using new Promise and Promise.resolve()
    return new Promise(resolve => {                                 // This is just a promise, necesiry to wait for it
        setTimeout(() => resolve('I want to be first'), 3000);
    });
};

const test1 = async () => {                                         // indirect Promise declaration usind async 
    return setTimeout(() => console.log("test1, I want to be executed first"), 3000);      // async => the function returns a promise hence return a resolve,
};                                                                  // we should use await to wait for the Promise.resolve()

/* create intermediate calling functions making code synchronous to use console.log() properly */
const doSomething = async () => {
    console.log( await doSomethingAsync());
};

const callTest = async () => {
    console.log("hope to be executed before test1() resolve");
    await test1();
    console.log("hope to be executed after test1() resolve");
}

/* hope to run code synchronously in the following using .then() keyword */
console.log('1');
doSomething();
console.log('2');
callTest();
console.log('3');
doSomething()
    .then(console.log("I want to be after"))
    .catch(error =>{
        console.log(error);
    });
console.log('4');
console.log( doSomethingAsync().then(console.log("I want to be after too")) );
console.log('5');
// hope to run code synchronously in the following using await keyword
(async () => {  

    let test2 = await doSomethingAsync();
    let test3 = await doSomething();
    await test1();

    console.log(`value doSomethingAsync: ${test2}`);
    console.log(`value doSomething: ${test3}`);
})();
console.log('6');

我期望的是看到Promise.resolve()触发后,将代码放入.then()关键字中以同步执行...但这不是我观察到的。在我的终端中查看以下程序输出:

ʘ node test_promises.js 
1
2
hope to be executed before test1() resolve
3
I want to be after
4
I want to be after too
Promise { <pending> }
5
6
hope to be executed after test1() resolve
test1, I want to be executed first
I want to be first
I want to be first
I want to be first
value doSomethingAsync: I want to be first
value doSomething: undefined
test1, I want to be executed first

从输出中可以明显看出.then()在被调用函数内的代码之前运行。

来自StackOverflow

  

异步任务完成后,then函数中的成功或错误处理程序将仅被调用一次。

似乎并非如此。因此,我的问题很简单:

  

问题:为什么在异步结束之前调用.then(),以及如何正确地使用Promises,.then()和async / await(应该替换掉)进行编码?

编辑

根据社区的回答,我了解到.then()在传递给它的值不是回调函数时直接触发。因此,通过像.then(function() {console.log("I want to be after")} )

这样修改.then()

好的,我不明白。我得到


    ʘ node test_promises.js 
    1
    2
    hope to be executed before test1() resolve
    3
    4
    Promise { <pending> }
    5
    6
    hope to be executed after test1() resolve
    test1, I want to be executed first
    I want to be after too
    I want to be first
    I want to be first
    I want to be after
    I want to be first
    value doSomethingAsync: I want to be first
    value doSomething: undefined
    test1, I want to be executed first

  

我仍然不明白为什么在调用

之前在console.log()触发之前
const callTest = async () => {
    console.log("hope to be executed before test1() resolve");
    await test1();
    console.log("hope to be executed after test1() resolve");
}

感谢社区的耐心

编辑2

来自社区的答案:

  

异步函数仅等待内部等待的内容   它的代码。它无法自动识别任何可以执行的呼叫   异步的东西。您需要明确承诺setTimeout   使它与承诺一起工作。 – Bergi ANSWER 2:返回setTimeout(()   => console.log(“ test1,我想先执行”),3000)不正确,因为setTimeout不会返回promise。转换中   使用回调的函数,例如setTimeout,而不使用其他函数   辅助函数有些罗word:返回新的Promise(resolve => {   setTimeout(resolve,3000); }); – Ry-♦

这意味着正确的代码如下:

    // declaration of some Promisified functions 
    const doSomethingAsync = () => {                                    
        return new Promise(resolve => {                                 
            setTimeout(() => resolve('I want to be first'), 3000);
        });
    };

    const test1 = async () => {                                                                                         // IMPORTANT CORRECTION: use Promise constructor
        return new Promise(resolve => { setTimeout( () => {resolve("test1, I want to be executed first")}, 3000); });   // actuallu async do not transform the return
    };                                                                                                                  // function into a Promise


    // create intermediate calling functions making code synchronous to use console.log() properly
    const doSomething = async () => {
        console.log( await doSomethingAsync());
    };

    const callTest = async () => {
        console.log("hope to be executed before test1() resolve");
        const resultTest1 = await test1();  // IMPORTANT CORRECTION: declare a variable to return the value of the executed function when exec is over, using await
        console.log(resultTest1);
        console.log("hope to be executed after test1() resolve");
    }

    // hope to run code synchronously in the following using .then() keyword 
    console.log('1');
    doSomething();
    console.log('2');
    callTest();
    console.log('3');
    doSomething()
        .then(function() {console.log("I want to be after")} )  // IMPORTANT CORRECTION: declare a callback function instead of executing the function
        .catch(error =>{
            console.log(error);
        });
    console.log('4');
    console.log( doSomethingAsync().then(function() {console.log("I want to be after too")}) );
    console.log('5');
    // hope to run code synchronously in the following using await keyword, THIS IS THE "RIGHT" WAY TO USE ASYNC/AWAIT
    (async () => {  

        let test2 = await doSomethingAsync();
        let test3 = await doSomething();
        await test1();  // this is the last await, it will be the last executed code

        console.log(`value doSomethingAsync: ${test2}`);
        console.log(`value doSomething: ${test3}`);
    })();
    console.log('6');

特别感谢所有提供帮助的人。我希望这会有用。

0 个答案:

没有答案