Функция asyn c возвращает неопределенный тип - PullRequest
0 голосов
/ 13 июля 2020

У меня есть асинхронная c функция, которая вызывает базу данных и возвращает строку (обещание). Однако, когда я вызываю эту функцию, я получаю undefined

Функция asyn c:

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

Затем я вызываю эту функцию отсюда, но получаю undefined в консоли:

client.on('message', async msg => {
    if(msg.content==='\'init'){
        initializeChannelDatabase(msg.channel.id).then(result=>{
            console.log(result);
            if(result===SUCCESS){
            ...

Ответы [ 3 ]

2 голосов
/ 13 июля 2020

Он не определен, потому что вы фактически ничего не возвращаете из функции initialiseChannelDatabase.

Поскольку вы используете asyn c, вы также должны использовать '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;
    }
}

Другая информация об asyn c / ожидание по этой ссылке

EDIT: удален внутренний try-catch, потому что в случае неудачи он вызовет первый улов, и все равно все будет в порядке.

1 голос
/ 13 июля 2020

Проблема в том, что вы никогда не вернетесь из initializeChannelDatabase. Единственные операторы возврата внутри него помещаются в обратные вызовы then и catch. Таким образом, они возвращаются из функции обратного вызова, а не из 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. Если целью было объединить успех и неудачу, вы можете оставить все как есть.

0 голосов
/ 13 июля 2020

Вы возвращаете Promise.resolve(SUCCESS), но переменная SUCCESS не определена в вашем коде. Вероятно, вы намеревались вернуть строку 'SUCCESS', как в документации MDN:

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