【问题标题】:Alexa responding before data is returnedAlexa 在数据返回之前做出响应
【发布时间】:2019-10-14 09:51:19
【问题描述】:

我对 promises、async/await 和 Alexa/lambda 不熟悉,所以请耐心等待。

我的函数在返回数据之前返回。我遇到了一个类似的问题,我遇到了一个错误,但后来我对我的函数进行了相当多的编辑,因此提出了一个新问题。我现在不再收到错误,而是首先返回我的数据,然后执行 promise。

在阅读了许多 SO、google 和 amazon 开发者论坛后,我尝试重新编写 promise/function。似乎没有什么对我有用。

const IntentRequest = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
    },
    async handle(handlerInput) {
        const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
        let responseData, promise;

         checkAuthenticationStatus(handlerInput,function(json){
            console.log('waited!')
            if(json.error) {
                return handlerInput.responseBuilder.speak(messages.NO_ACCESS).withSimpleCard('Unauthorized Request', messages.NO_ACCESS).getResponse();
            } else if(json.noerror && json.noerror.okay == 'true'){
                console.log('starting to get intent data')
                const url = new URL(json.noerror.okay.path);
                promise = new Promise((resolve, reject) => { 
                    console.log('start promise')
                   return httpsGetIntent(handlerInput, url).then((resultData) => {
                        console.log(resultData)
                        responseData = resultData;
                        resolve(responseData)
                        console.log('inside promise, no error, prior to return data')
                    })

            }).then((result) => { console.log('result', result)})
                return handlerInput.responseBuilder.speak('Test').getResponse();
            }

        });
        console.log('response data', responseData)

        let result = await promise;
        return result;

    },
};

在我为调试添加的许多 console.logs() 中,它们打印如下: - '响应数据' - “等待!” - '开始获取意图数据' - '开始承诺' - 结果数据 - '内部承诺,没有错误,在返回数据之前'

【问题讨论】:

  • 正如所写,return handlerInput.responseBuilder.speak('Test').getResponse(); 不在 .then 回调中,尽管缩进使它看起来不是这样。还有其他问题需要解决。
  • 感谢@Roamer-1888!我昨晚实际上解决了这个问题,并且即将发布我的答案。

标签: node.js lambda promise alexa alexa-skills-kit


【解决方案1】:

虽然它还没有完全充实(我需要解决错误处理部分),但我想在这里分享我的解决方案,以防有人偶然发现这篇文章并需要一些帮助。

我将 promise 移到 checkAuthentication 函数之外,并在处理数据时返回数据。然后我用 .then() 将 promise 链接起来,并将返回的数据传递给它,并提示 Alexa 说话。

const IntentRequest = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
    },
    async handle(handlerInput) {
        const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
        let responseData, promise;
        return new Promise((resolve, reject) => {
            checkAuthenticationStatus(handlerInput, async function(json) {
                if (json.error) {
                    return handlerInput.responseBuilder.speak(messages.NO_ACCESS).withSimpleCard('Unauthorized Request', messages.NO_ACCESS).getResponse();
                } else if (json.noerror && json.noerror.okay == 'true') {
                    const url = new URL(json.noerror.okay.path);
                    let resultD = await httpsGetIntent(handlerInput, url, function(resultData) {
                        if (resultData) {
                            return resolve(resultData);
                        } else {
                            return resolve(handlerInput.responseBuilder.speak('False Test').getResponse());
                        }
                    })

                }
            })

        }).then((data) => {
            return handlerInput.responseBuilder.speak(data.response.outputSpeech.text).getResponse();
        });
    },
};

【讨论】:

  • httpsGetIntent() 有点混乱。一方面,你 await 它(表示它返回 Promise),而另一方面,它接受回调。通常,一个函数(或任何特定调用)会表现出一种或另一种行为。
  • @Roamer-1888 感谢您的帮助!我不完全理解 async/await 并引用了其他一些 alexa 示例
【解决方案2】:

Almost_Ashleigh,根据您自己的回答,我的一些想法:

  1. 假设httpsGetIntent() 返回一个传递resultData 的Promsie。
  2. 通过编写适配器checkAuthenticationStatusAsync() 承诺checkAuthenticationStatus()
  3. .speak() 命令合并到最终的.then().catch() 子句中。
  4. 允许通过使用.title 属性进行修饰来定制特定错误,该属性在最终.catch() 中用作卡片标题。任何未修饰的错误都将默认为“抱歉”(或任何您想要的)。
// in a suitable scope ...
function checkAuthenticationStatusAsync(handlerInput) {
    return new Promise((resolve, reject) {
        checkAuthenticationStatus(handlerInput, (json) => {
            if (json.error || !json.noerror || json.noerror.okay !== 'true') {
                let err = new Error(messages.NO_ACCESS); // or maybe a separate error message per error case?
                err.title = 'Unauthorized Request';
                reject(err);
            } else {
                resolve(json);
            }
        });
    });
}

// ... and ...
const IntentRequest = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
    },
    handle(handlerInput) {
        return checkAuthenticationStatusAsync(handlerInput)
        .then((json) => httpsGetIntent(handlerInput, new URL(json.noerror.okay.path)))
        .then((resultData) => {
            if (resultData) {
                // success path ends here
                return handlerInput.responseBuilder.speak(resultData.response.outputSpeech.text).getResponse();
            } else {
                throw new Error('No result data returned'); // throws to the .catch() below
            }
        })
        .catch(err => {
            // all errors end up here.
            return handlerInput.responseBuilder.speak(err.message).withSimpleCard(err.title || 'Sorry', err.message).getResponse();
            throw err; // to keep handle's caller informed
        });
    },
};

注意,这是一种的方式,不一定是的方式,来写代码。请随意突袭以寻求想法。

【讨论】:

    【解决方案3】:

    你最好的朋友是 async/await。请使用 thisthis 之类的名称来访问 API。

    【讨论】:

    • 感谢您提供这些示例!我会尝试实现它们
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    相关资源
    最近更新 更多