没有回应。这是否在未作为承诺返回的异步调用中使用

问题描述 投票:1回答:2

我收到了以下错误。

Error: No response has been set. Is this being used in an async call that was not returned as a promise to the intent handler?
    at DialogflowConversation.response (/user_code/node_modules/actions-on-google/dist/service/actionssdk/conversation/conversation.js:162:19)
    at DialogflowConversation.serialize (/user_code/node_modules/actions-on-google/dist/service/dialogflow/conv.js:134:89)
    at Function.<anonymous> (/user_code/node_modules/actions-on-google/dist/service/dialogflow/dialogflow.js:154:28)
    at next (native)
    at fulfilled (/user_code/node_modules/actions-on-google/dist/service/dialogflow/dialogflow.js:19:58)
    at process._tickDomainCallback (internal/process/next_tick.js:135:7)

我将发布我的代码,在此我已经使用了承诺。如果我在承诺实施中出错,请纠正我。

public  getTodaysEntryOfUser(conv: any) : any {
            this.getDataFromDatabase(conv).then((todaysEntry) => {
                conv.ask('<speak>Welcome to my applicatoion <break time="1"/> </speak>');
                let question:Question =  this.getStartQuestion(1);
                conv.ask('<speak>'+question.ask+'</speak>');
                conv.data.kind  = question.resolution.kind;
                return question;
            })
            .catch(err => {
                console.log('Error getting document', err);
                return err;
             });

        }

“getDataFromDatabase”方法的代码

public async getDataFromDatabase(conv: any) : Promise<any> {
            let getPromise  =   await this.getDAOaccess(conv);
            return getPromise;
        }

getDAOaccess方法的代码

private getDAOaccess(conv:any) : Promise<any>{
            return new Promise<any>((resolve,reject) => {
                this.getDataFromDB(conv,(err:any,response:any)=>{
                    if(err)
                        reject(err);
                    else
                        resolve(response);
            });
        });

        }

getDataFromDB方法的代码

private getDataFromDB(conv:any, callback: (err:any,response:any) => void ) : Promise<any> {
            let  self    =   this;
            let documentDetail;
            let subjectId    =   conv.request.user.userId;
            let questionID   =   conv.request.user.questionID;
            let docRef=  this.dbManager.collection('question').doc(subjectId);
            return new Promise((resolve, reject) => {
                docRef.get().then(doc => {
                   documentDetail  =   doc;
                   conv.user.response= doc.data();
                   return resolve(doc.data());
                })
                .catch(err => {
                   console.log('Error getting document', err);
                   reject(err);
                });

            });
        }

请让我知道代码中的问题。提前致谢

typescript firebase google-cloud-firestore google-cloud-functions actions-on-google
2个回答
3
投票

问题是getTodaysEntryOfUser()没有回归承诺。假设这是一个intent处理程序(你没有显示你如何注册它,如果是这样),Dialogflow库会将不返回Promise的函数视为所有同步操作并立即处理它。

如果要进行异步调用,则需要确保:

  1. 你调用conv.ask()作为解决Promise的一部分
  2. 你返回一个承诺

在这种情况下,它可能就像确保你把return放在线之前一样简单

this.getDataFromDatabase(conv).then(

1
投票

你的方法getDataFromDB似乎很困惑。您已经定义了一个从未使用过的参数callback。相反,该方法返回一个Promise但是当你调用它时,你忽略了返回的值,因为你传递了未使用的callback参数。

更改getDAOaccess以使用Promise

private getDAOaccess(conv:any) : Promise<any>{
        return this.getDataFromDB(conv);
    }

现在很明显getDAOaccess什么都不做,所以你可以从代码中删除它,只需直接从getDataFromDB调用getDataFromDatabase

这段代码也很混乱。它返回一个Promise所以你实际上不需要await内部调用,只需返回它返回的Promise

public async getDataFromDatabase(conv: any) : Promise<any> {
        let getPromise  =   await this.getDAOaccess(conv);
        return getPromise;
    }

应该:

public getDataFromDatabase(conv: any) : Promise<any> {
        return this.getDataFromDB(conv);
    }

现在你看到这个方法也没有做任何事情。

现在外部呼叫有问题。您想要返回结果,但内部调用是异步的。可能最好的方法是将此方法标记为async

public async getTodaysEntryOfUser(conv: any) {
    const todaysEntry = await this.getDataFromDB(conv);
    conv.ask('<speak>Welcome to my applicatoion <break time="1"/> </speak>');
    let question:Question =  this.getStartQuestion(1);
    conv.ask('<speak>'+question.ask+'</speak>');
    conv.data.kind  = question.resolution.kind;
    return question;
}

这个方法现在返回一个Promise<Question>你需要像任何其他Promise一样处理getTodaysEntryOfUser(如果数据库调用失败,Promise将拒绝,拒绝只是向上传播所以不需要return err任何地方。注意你没有必要告诉编译器返回类型,它会正确地为它自己解决。你也应该避免将任何参数声明为any类型,找出更好的错误消息的实际类型。

© www.soinside.com 2019 - 2024. All rights reserved.