NodeJS -为什么我不能在我的主程序中使用“等待”?Hangs...什么是“模块”,什么是“顶级”-即

iaqfqrcu  于 2023-01-25  发布在  Node.js
关注(0)|答案(1)|浏览(515)

我想做什么-使用"AWAIT"关键字,这样我就可以在程序结束和挂起之前得到结果。我读了几十个博客,答案如下:
1.使用await关键字,简单
1.使用async(){}换行
1.有人说根本不需要等待。
但这些对我还没起作用。

const redis = require('ioredis');
const REDIS_RELATIX_HOST = "redis-xxxx.c277.us-east-1-3.ec2.cloud.redislabs.com"
const REDIS_RELATIX_PORT =  "12269"
const REDIS_RELATIX_PASSWORD = "mypassword"

let result = "dummy";       
const redisClient = redis.createClient({
            host: REDIS_RELATIX_HOST,
            port: REDIS_RELATIX_PORT,
            password: REDIS_RELATIX_PASSWORD 
        }) 
redisClient.on('error', err => {
    console.log('Error ' + err);
    });
await getSpanishWordForRed(); 
Console.Write("result=" + result); 
     
async function getSpanishWordForRed(){
    console.log("getSpanishWordForRed:start")
    await redisClient.hget('spanish', 'red', 
                           (err, value) => {
        if (err) console.log(err);
        else {
             console.log(value);
             result = value.toString(); 
             }
    });
    console.log("getSpanishWordForRed:end")
}

console.log("The end")  // I've tried with and without this line - just for fun.

我看过一些帖子说你可以直接调用async函数,但这就是我得到的。

await getSpanishWordForRed();
^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules

这就提出了两个问题:
1.我不是在一个模块里吗?
1.我不是在"最高层机构"吗?
所以我想,如果我把代码分成两个例程,一个是模块,但问题是,我仍然需要在主程序中有"await",不是吗,它不是模块?
我创建了一个主例程:

var mySpanishWord = require('./redisTestNodeOnly8Module.js') 
console.log("main before await result"); 
result = mySpanishWord();
console.log("main result=" + result);

然后我想我创建了一个"模块"(文件名:redisTestNodeOnly 8模块. js):

exports.SpanishWordForRed = async function() {
    const redis = require('ioredis');
    const REDIS_RELATIX_HOST = "redis-xxxxx.c277.us-east-1-3.ec2.cloud.redislabs.com"
    const REDIS_RELATIX_PORT =  "12269"
    const REDIS_RELATIX_PASSWORD = "mypassword"

    const redisClient = redis.createClient({
                host: REDIS_RELATIX_HOST,
                port: REDIS_RELATIX_PORT,
                password: REDIS_RELATIX_PASSWORD 
            }) 
    redisClient.on('error', err => {
        console.log('Error ' + err);
        });
        
    let result = "dummy";       
    console.log("getSpanishWordForRed:start")
    await redisClient.hget('spanish', 'red', 
                           (err, value) => {
        if (err) console.log(err);
        else {
             console.log(value);
             result = value.toString(); 
             return value.toString(); 
             }
    });
    
}

结果:

c:\GitHub\Relatix\Apps\CMS_Bad2\src>node redisTestNodeOnly8.js
main before await result
getSpanishWordForRed:start
main result=[object Promise]
The end
rojo
^C

这是一个已经很长的问题的简化版:Redis 4.5.1 - hanging in NodeJS 18我想把这个问题限制在"模块"和"顶级"错误的问题上,以及如何解决这个问题。
这是我之前尝试过的东西(redisTestNodeOnly7Module,是的,还有其他六个redis、ioredis的变体,没有一个工作)。

const redis = require('ioredis');
const REDIS_RELATIX_HOST = "redis-xxxxx.c277.us-east-1-3.ec2.cloud.redislabs.com"
const REDIS_RELATIX_PORT =  "12269"
const REDIS_RELATIX_PASSWORD = "mypassword"

let result = "dummy";       
const redisClient = redis.createClient({
            host: REDIS_RELATIX_HOST,
            port: REDIS_RELATIX_PORT,
            password: REDIS_RELATIX_PASSWORD 
        }) 
redisClient.on('error', err => {
    console.log('Error ' + err);
    });
console.log("before call runRedis()");
// wordPromise = await getSpanishWordForRed(); 
(async function() {
    const wordPromise = await getSpanishWordForRed();
    //console.log("after call runRedis() wordPromise=" + wordPromise.toString() ); 
    //console.log("after call runRedis() wordPromise=" + wordPromise.resolve()); 
    console.log("after call runRedis() result=" + result);  
})();
     
async function getSpanishWordForRed(){
    console.log("getSpanishWordForRed:start")
    await redisClient.hget('spanish', 'red', 
                           (err, value) => {
        if (err) console.log(err);
        else {
             console.log(value);
             result = value.toString(); 
             }
    });
    console.log("getSpanishWordForRed:end")
}

console.log("The end")

结果(仍然显示"结束"之前的理论"等待"发生"):

before call runRedis()
getSpanishWordForRed:start
The end
rojo
getSpanishWordForRed:end
after call runRedis() result=rojo
^C

更新-这是我的"副本"马特的代码,和结果。
我仍然得到"rojo"作为西班牙语单词红色回来,但程序仍然"挂起"。如果我运行"节点program.js",它应该只是结束,并返回到命令提示符正常?我必须点击CNTL-BREAK杀死它。

const redis = require('ioredis');
        const REDIS_RELATIX_HOST = "redis-xxxxx.c277.us-east-1-3.ec2.cloud.redislabs.com"
        const REDIS_RELATIX_PORT =  "12269"
        const REDIS_RELATIX_PASSWORD = "mypassword"
    
    let result = "dummy";       
    const redisClient = redis.createClient({
                host: REDIS_RELATIX_HOST,
                port: REDIS_RELATIX_PORT,
                password: REDIS_RELATIX_PASSWORD 
            }) 
    redisClient.on('error', err => {
        console.log('Error ' + err);
        });
    redisClient.on('connect', () => {
        console.log('Connected to Redis');
        });
         
    async function getSpanishWordForRed(){
        console.log("getSpanishWordForRed:start")
        return redisClient.hget('spanish', 'red')
    }
    
    async function go(){
        console.log("go():start")
        const result = await getSpanishWordForRed()
        console.log("go():end result=", result)
        // put the rest of the control flow inside go. 
    }
    
    // Use this as the commonjs entry, so things are `await`able
    go().catch(err => {
        console.error("go/catch error:" + err)
        process.exit(1)
    })

console.log("The end")

执行:

c:\Demo\src>node redisTestNodeOnlyStackOverflowMatt.js
go():start
getSpanishWordForRed:start
The end
Connected to Redis
go():end result= rojo
^C
xe55xuns

xe55xuns1#

错误await is only valid in async functions and the top level bodies of modules中的modules术语指的是ECMAScript module。文件需要使用扩展名.mjs,或者在package.json中标记为"type": "module"并使用import语法。
代码对await getSpanishWordForRed()的初始调用是“顶级”的,所以在节点Common JS模块中不起作用,使用require()语法。CommonJS是可以的,下面的例子详细介绍了一种稍微不同的方式来初始化异步函数调用。
对于ioredis,示例代码似乎与文档中的连接API不匹配。可能挂起与缺乏连接有关?

const Redis = require("ioredis")
const redisClient = new Redis({
    port: REDIS_RELATIX_PORT,
    host: REDIS_RELATIX_HOST,
    username: "default", //??
    password: REDIS_RELATIX_PASSWORD,
})
redisClient.on('connect', () => {
    console.log('connected to', REDIS_RELATIX_HOST);
});
redisClient.on('error', err => {
    console.error('Error', err);
});

代码还混合了Promise/await API和Callback API,方法是提供一个函数作为最后一个参数,只需使用Promise而不使用回调函数:

async function getSpanishWordForRed(){
    return redisClient.hget('spanish', 'red')
}

async function go(){
    console.log("getSpanishWordForRed:start")
    const result = await getSpanishWordForRed()
    console.log("getSpanishWordForRed:end", result)
    // put the rest of the control flow inside go. 
}

// Use this as the commonjs entry, so things are `await`able
go().catch(err => {
    console.error(err)
    process.exit(1)
}

使用此入口点将删除顶级等待/模块问题。

相关问题