异步等待正确使用

Posted

技术标签:

【中文标题】异步等待正确使用【英文标题】:Async await correct usage 【发布时间】:2020-09-10 21:19:26 【问题描述】:

我已经阅读了一些关于 async/await 的文档,并尝试通过一个示例来更好地理解它。我所期待的是,下面没有 async 和 await 的代码将首先打印字符串“Completed”,然后是文件的内容。但即使在添加了 async 和 await 之后,我也看到打印顺序没有受到影响。我的印象是异步的,在这种情况下等待使用将首先打印文件内容,然后是字符串“已完成”。

var fs = require('fs');

getTcUserIdFromEmail();

async function getTcUserIdFromEmail( tcUserEmail ) 

    let userInfo = ;
    let userFound = false;
    // Read the file that is containing the information about the active users in Teamcenter.
    await fs.readFile('tc_user_list.txt', function(err, data) 

        if( err )
        console.log( err );
        else
        console.log( data.toString() );
    );

    console.log( 'Completed method');

请你指出我做错了什么。

谢谢, 帕万。

【问题讨论】:

你认为await 是做什么的?你为什么要把它和回调混在一起? fs.readFile() 不返回承诺。 Using filesystem in node.js with async / await await 只有在等待承诺时才会做任何有用的事情。 fs.readFile() 的常规版本不返回承诺,因此等待它没有任何用处。您可以使用fs.promises.readFile(),它将返回一个承诺并且不接受回调。结果来自等待的承诺,而不是通过回调。 @GuyIncognito 它使用 fs.promises 工作,如另一个线程中所述。谢谢。 fs.promises.readFile() 不接受回调。看the documentation。结果或错误会在 Promise 中返回,而不是在回调中。如果你向它传递一个回调,该回调将永远不会被调用。当您使用 Promise 进行编程时,您会在 Promise 中返回您的结果或错误。当你等待一个承诺时,你会得到const data = await fs.promises.readFile(someFile)的结果,你会用try/catch捕获错误。 【参考方案1】:

await 仅在等待的表达式返回 Promise 时才有效。 fs.readFile 不返回承诺,所以现在你的 await 不做任何事情。

对我们来说幸运的是,node 提供了一个函数 fs.promises.readFile,它类似于 fs.readFile,但不是期待回调,而是返回一个 Promise。

const fs = require('fs')

现在你可以await fs.promises.readFile(...)

getTcUserIdFromEmail(); // > contents_of_tc_user_list
                        //   Completed method

async function getTcUserIdFromEmail( tcUserEmail ) 
    let userInfo = ;
    let userFound = false;
    const data = await fs.promises.readFile('tc_user_list.txt')
    console.log(data.toString())
    console.log( 'Completed method');

【讨论】:

fs.promises.readFile() 已经存在时,无需承诺fs.readFile()。此外,您需要表明调用getTcUserIdFromEmail() 本身需要使用await.then() 才能知道它何时完成,因为它也返回一个promise。 @jfriend00 请原谅我,但据我了解,对于每个异步方法,异步方法的调用者都应该“等待”它。这是因为没有回调。这种理解是否正确。 如果您只想查看日志消息,则不必等待getTcUserIdFromEmail()。当所有异步内容解决时,您的节点进程将退出。但是,如果您想使用getTcUserIdFromEmail() 的返回值,您绝对必须等待,但是 @jfriend00 我不知道fs.promises,我会更新我的答案以使用它,谢谢! @PavanDittakavi - 如果您想知道返回承诺的异步函数何时完成或是否有错误,您必须使用 awaittry/catch.then()和/或.catch()

以上是关于异步等待正确使用的主要内容,如果未能解决你的问题,请参考以下文章

等待 dispatch_semaphore 以等待许多异步任务完成的正确方法

通过节点的异步/等待不需要按预期顺序返回结果 - 使用啥正确模式?

等待异步函数在 dart 中无法正确执行

将 HttpContext.Current.User 与异步等待一起使用的正确方法

使用异步方法等待 Task.Run 不会在正确的线程上引发异常

如何正确使用等待和通知方法?