Javascript 异步函数返回未定义的类型
我有一个异步函数,它调用数据库并返回字符串(promise)。然而,当我调用这个函数时,我得到了未定义的结果 异步函数:Javascript 异步函数返回未定义的类型,javascript,asynchronous,discord.js,Javascript,Asynchronous,Discord.js,我有一个异步函数,它调用数据库并返回字符串(promise)。然而,当我调用这个函数时,我得到了未定义的结果 异步函数: const SUCCESS = 'Channel storage initialized succesfully'; const FAIL = 'There has been a problem initializng this channel'; const EXISTS = 'Channel already initialized' initializeChannelD
const SUCCESS = 'Channel storage initialized succesfully';
const FAIL = 'There has been a problem initializng this channel';
const EXISTS = 'Channel already initialized'
initializeChannelDatabase = async channelNum =>{
const db = admin.firestore();
db.collection('channels').doc(channelNum).get().then(res=>{
if(!res.exists){
db.collection('channels').doc(channelNum).set({isPremium: false}).then(res=>{
return Promise.resolve(SUCCESS);
}).catch(err=>{
return Promise.resolve(FAIL);
})
}else{
return Promise.resolve(EXISTS);
}
}).catch(err=>{
return Promise.resolve(FAIL);
})
}
然后我从这里调用此函数,但在控制台中未定义:
client.on('message', async msg => {
if(msg.content==='\'init'){
initializeChannelDatabase(msg.channel.id).then(result=>{
console.log(result);
if(result===SUCCESS){
...
您返回
Promise.resolve(SUCCESS)
但变量SUCCESS
在代码中未定义。
您的意图可能是像MDN文档中那样返回字符串'SUCCESS'
:
Promise.resolve('Success')。然后(函数(值){
console.log(值);/“成功”
},函数(值){
//不打电话
});
它是未定义的,因为您实际上没有从initialiseChannelDatabase
函数返回任何内容
由于您使用的是async,因此在使用异步函数时还应使用“wait”,这样在不使用额外闭包和回调的情况下,处理这种情况会更容易:
initializeChannelDatabase = async channelNum => {
const db = admin.firestore();
try {
let channelDoc = await db.collection('channels').doc(channelNum).get();
if (!channelDoc.exists) {
await db.collection('channels').doc(channelNum).set({ isPremium: false });
return SUCCESS;
} else {
return EXISTS;
}
} catch (err) {
return FAIL;
}
}
关于异步/等待的其他信息
编辑:删除了内部try-catch,因为如果失败,它将触发第一个catch,并且无论如何都会正常。问题是您永远不会从
initializeChannelDatabase返回。其中唯一的返回语句放在然后和catch
回调中。因此,它们从回调函数返回,而不是从initializeChannelDatabase
返回
在承诺前添加return
语句然后
/catch
链应该可以解决问题并返回承诺链生成的最终承诺
initializeChannelDatabase = async channelNum => {
const db = admin.firestore();
return db.collection('channels').doc(channelNum).get().then(res=>{
// ^ return the promise chain
if(!res.exists){
return db.collection('channels').doc(channelNum).set({isPremium: false}).then(res=>{
// ^ return the nested promise chain
return Promise.resolve(SUCCESS);
}).catch(err=>{
return Promise.resolve(FAIL);
})
}else{
return Promise.resolve(EXISTS);
}
}).catch(err=>{
return Promise.resolve(FAIL);
})
}
initializeChannelDatabase = async channelNum => {
const db = admin.firestore();
try {
const channel = await db.collection('channels').doc(channelNum).get();
if (channel.exists) return EXISTS;
await db.collection('channels').doc(channelNum).set({isPremium: false});
return SUCCESS;
} catch (error) {
return FAIL;
}
}
但是,由于您的函数已经使用了async
关键字,因此您最好使用wait
功能,而不是构建承诺链
initializeChannelDatabase = async channelNum => {
const db = admin.firestore();
return db.collection('channels').doc(channelNum).get().then(res=>{
// ^ return the promise chain
if(!res.exists){
return db.collection('channels').doc(channelNum).set({isPremium: false}).then(res=>{
// ^ return the nested promise chain
return Promise.resolve(SUCCESS);
}).catch(err=>{
return Promise.resolve(FAIL);
})
}else{
return Promise.resolve(EXISTS);
}
}).catch(err=>{
return Promise.resolve(FAIL);
})
}
initializeChannelDatabase = async channelNum => {
const db = admin.firestore();
try {
const channel = await db.collection('channels').doc(channelNum).get();
if (channel.exists) return EXISTS;
await db.collection('channels').doc(channelNum).set({isPremium: false});
return SUCCESS;
} catch (error) {
return FAIL;
}
}
我还强烈建议使用thow FAIL/EXISTS
而不是return FAIL/EXISTS
。这将确保退回的承诺被拒绝。将调用者置于备用捕获路径中。如果目的是将成功和失败合并在一起,则可以保持原样。它们在代码中以前定义为字符串。很抱歉没有包括我认为没有必要的内容。我已经编辑了代码,在顶部包含了字符串。我想退回其中一个。如果.then()执行成功,如果.catch()执行失败,请注意当channel.EXISTS
为true时,用户返回的内容存在。答案很好:)@Drago96很好,在将if语句转换为保护子句时忘记了反转if语句。我已经更新了代码。