【问题标题】:Question about JS Async / Sync return issue关于 JS Async / Sync 返回问题的问题
【发布时间】:2021-03-01 21:44:03
【问题描述】:

我需要一些关于 js 异步/同步的帮助。我阅读了很多帖子、youtube 视频等,但我不明白我的问题。我遇到的问题是我使用了一些异步函数,这些函数将在处理后返回一个值,并在主函数中使用这个返回值来响应 get 调用。

我有一个 NodeJS Express 设置,当我转到特定链接时,我的服务器收到了一个请求并执行了一个函数。

server.get('/info', (req, res) => {
    //res.send('Hello this is the API for sysinfo!');
    //res.writeHead(200, {'Content-Type': 'application/json'});
    console.log(getCpuInformation());
});

function getCpuInformation() {
    si.currentLoad()
    .then(data => {
        var cpuUsage = Math.round(data.currentload);
        console.log(`CPU Usage : ${cpuUsage}%`);
        return cpuUsage;
    })
    .catch(error => {
        console.error(`Error during the request of the CPU : ${error}`);
    });
}

getCpuInformation 中的 console.log 运行良好,因为它正在等待 si.currentLoad 的结果写入,但 server.get 中的 console.log 写入未定义,因为我猜它不会等待返回(或者返回实际在 si.currentLoad 结束之前返回)。

你能帮帮我吗?

【问题讨论】:

    标签: javascript node.js express asynchronous return


    【解决方案1】:

    因此,感谢您的一些答复,我更改了代码,但现在我需要弄清楚在获取信息后如何将其发送回发出请求的客户。而我所做的改变是好还是坏?

    server.get('/info', (req, res) => {
        //res.send('Hello this is the API for sysinfo!');
        getAllInformation((resultReturned) => {
            console.log(resultReturned);
        });
    });
    
    async function getAllInformation(myCallBack) {
        var cpuUsage = await getCpuInformation();
        // more inc
        myCallBack(cpuUsage);
    }
    
    async function getCpuInformation() {
        try {
            const data = await si.currentLoad();
            var cpuUsage = Math.round(data.currentload);
            //console.log(`CPU Usage : ${cpuUsage}%`);
            return JSON.stringify({ "cpuUsage": cpuUsage});
        } catch(error) {
            //console.log(`Error during the request of the CPU : ${error}`);
            return JSON.stringify({ "cpuUsage": "ERROR"});
        }
    }
    

    【讨论】:

    • 你不需要getAllInformation 中的回调和异步。使用一个或另一个。如果您不喜欢我的回答 - 请参阅 @user2740650
    【解决方案2】:

    试试这样的:

    server.get('/info', async (req, res) => {
        //res.send('Hello this is the API for sysinfo!');
        //res.writeHead(200, {'Content-Type': 'application/json'});
        console.log(await getCpuInformation());
    });
    
    async function getCpuInformation() {
        try {
            const data = await si.currentLoad();
            var cpuUsage = Math.round(data.currentload);
            console.log(`CPU Usage : ${cpuUsage}%`);
            return cpuUsage;
        } catch (error) {
            console.error(`Error during the request of the CPU : ${error}`);
        };
    }
    

    【讨论】:

    • 这是我尝试的第一件事,但你不能在同步函数中使用等待,如果你添加一个由 server.get 调用并调用 getCpuInformation 的异步函数,也会这样做。
    • 正确,这就是为什么它不是同步功能。仔细看。我添加了async 关键字。
    • 没有改变任何东西,你添加了异步,就像我在上一条评论中告诉你的那样,但是 get 仍然是同步的(不能在里面使用 await)
    • 但是 express 允许在 get 上使用异步函数,我自己的代码就是这样做的。那么server 是什么,如果它不是一个快递应用程序呢?您的问题带有 express 标记。我自己的代码可以正常工作是const app = express(); app.get('/test/', async (req, res) => {
    • 你说得对,我只是忘了在 server.get 上添加异步,我的错,我猜需要睡觉......
    【解决方案3】:

    您的getCpuInformation 函数永远不会返回任何值。 线

    return cpuUsage;
    

    指的是你传递给.then而不是getCpuInformation函数的回调函数。

    您需要将getCpuInformation 转换为异步函数/承诺或使用这样的回调函数:

    server.get('/info', (req, res) => {
        //res.send('Hello this is the API for sysinfo!');
        //res.writeHead(200, {'Content-Type': 'application/json'});
        getCpuInformation((resultReturned) => console.log(resultReturned));
    });
    
    function getCpuInformation(myCallBack) {
        si.currentLoad()
        .then(data => {
            var cpuUsage = Math.round(data.currentload);
            console.log(`CPU Usage : ${cpuUsage}%`);
            myCallBack(cpuUsage);
        })
        .catch(error => {
            console.error(`Error during the request of the CPU : ${error}`);
        });
    }
    

    【讨论】:

    • 感谢您提供此信息,您的版本现在可以正常工作我需要了解为什么以及如何使用 await 等进行转换
    • 这个答案只对了一半。这里的解决方案是添加一个return,所以它是return si.currentLoad().then(...).catch(...)。然后getCpuInformation() 返回它的promise,调用者可以在返回的promise 上使用await.then() 来获得所需的值。无需将此函数转换为回调甚至async
    • @jfriend 你错了。有人打电话给si.currentLoad().then,这是一个承诺。并且等待的结果在承诺中。这就是为什么作者需要将其转换为 async/promise/callback
    • 是的,si.currentLoad().then().catch() 返回一个 Promise,并且该 Promise 需要从函数中获取 RETURNED,以便函数的调用者可以使用该 Promise 访问已解析的值。你显然不明白你是如何从一个函数中返回一个 promise 并让调用者使用 .then()await 从 promise 中获取值的。您不会在 Promise 之上添加自定义回调。这是一种反模式。
    猜你喜欢
    • 2023-02-13
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    • 2018-03-23
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多