异步函数返回未定义的类型

时间:2020-07-13 16:51:10

标签: javascript asynchronous discord.js

我有一个异步函数,该函数调用数据库并返回一个字符串(承诺)。但是,当我调用此函数时,我无法定义

异步功能:

printf -v "$2" '%s' "$answer"

然后我从这里调用此函数,但是在控制台中未定义它:

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);
    })
}

3 个答案:

答案 0 :(得分:2)

它是未定义的,因为您实际上并没有从initialiseChannelDatabase函数返回任何内容。

由于您使用的是异步功能,因此在使用异步功能时也应使用“ await”,这样可以更轻松地处理这种情况,而无需其他闭包和回调:

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;
    }
}

有关异步的其他信息/等待this link

编辑:删除了内部try-catch,因为在失败的情况下,它将触发第一个捕获,并且还是可以的。

答案 1 :(得分:1)

问题在于您永远不会从initializeChannelDatabase返回。其中唯一的return语句位于thencatch回调中。因此它们是从回调函数返回的,而不是从initializeChannelDatabase返回的。

在您的诺言return / then链之前添加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);
    })
}

但是,由于您的函数已经使用了async关键字,因此您最好也使用await功能而不是构建承诺链。

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。这将确保返回的诺言被拒绝。使呼叫者进入备用catch路径。如果打算将成功和失败合并在一起,则可以保留原样。

答案 2 :(得分:-2)

您返回Promise.resolve(SUCCESS),但是变量SUCCESS在代码中未定义。 您的意图可能是像MDN文档中那样返回字符串'SUCCESS'

Promise.resolve('Success').then(function(value) {
  console.log(value); // "Success"
}, function(value) {
  // not called
});