简体   繁体   中英

Alexa sdk v2 using ask-sdk-core custom skill fails with : Session ended with reason: ERROR

I'm developing a custom skill and having some trouble with just this intent, that is to say at the very last stage when all conditions are met in the if/else control flow, I mean when it gets to the last else statement, only this one fails to return the expected response, but all returned responses are working just fine, what could I possibly be missing here: Please pay close attention to the last part where resolve(handlerInput.responseBuilder.speak....etc). I'm not sure what I am doing right here, I'd appreciate

const SetDefaultLocationIntentInProgress = {
      canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
        && handlerInput.requestEnvelope.request.intent.name === 'SetDefaultLocationIntent';
      }, 
       handle(handlerInput) {
        console.log(`In SetDefaultLocationIntentInProgress`);
        let cardTitle = speech.getCardTitle('setdefaultloc1');

        let city = '';
        let state = '';
        let zipcode = '';


        const { attributesManager, responseBuilder } = handlerInput;
        const sessionAttributes = attributesManager.getSessionAttributes();

        const currentIntent = handlerInput.requestEnvelope.request.intent;


        if (sessionAttributes[currentIntent.name]) {
            const tempSlots = sessionAttributes[currentIntent.name].slots;
            for (const key in tempSlots) {
                if (tempSlots[key].value && !currentIntent.slots[key].value) {
                    currentIntent.slots[key] = tempSlots[key];
                }
            }
        }

        sessionAttributes[currentIntent.name] = currentIntent;
        attributesManager.setSessionAttributes(sessionAttributes);

        if (currentIntent.slots.City && currentIntent.slots.City.value) {
            // User provided value for City slot
            city = currentIntent.slots.City.value;
        }

        if (currentIntent.slots.State && currentIntent.slots.State.value) {
            // User provided value for State slot
            state = currentIntent.slots.State.value;
        }

        if (currentIntent.slots.Zipcode && currentIntent.slots.Zipcode.value) {
            // User provided value for Zipcode slot
            zipcode = currentIntent.slots.Zipcode.value;
        }

        debugLog(`City: ${city}, State: ${state}, Zipcode: ${zipcode}`);

        let speechOutput = '';
        let repromtText = '';

        if (city.length === 0 && state.length === 0 && zipcode.length === 0) {
            // No values provided by user for city, state or zipcode
            speechOutput = speech.getSpeechText('setdefaultloc5');
            repromtText = speech.getSpeechText('reprompt2');
            return handlerInput.responseBuilder
            .speak(speechOutput)
            .reprompt(repromtText)
            .withSimpleCard(cardTitle, speechOutput)
            .withShouldEndSession(false)
            .getResponse();
        }else if(zipcode.length > 0 && !zipCodeValidator(zipcode) ) {
            // user provided a zipcode but it is not a valid US zipcode
            let speechObject = speech.getSpeechObject('setdefaultloc7');
            speechOutput = util.format(speechObject.text, zipcode);
            repromtText = speech.getSpeechText('reprompt3');
            return handlerInput.responseBuilder
            .speak(speechOutput)
            .reprompt(repromtText)
            .withSimpleCard(cardTitle, speechOutput)
            .withShouldEndSession(false)
            .getResponse();

        }else {

            let params = '';
            let lookupFunc = '';
            let placeNameLookup = '';
            if (zipcode.length > 0 && zipCodeValidator(zipcode)) {
                params = zipcode;
                lookupFunc = apiCalls.zipcodeLookup;
            }else {
                if (state.length === 0) {
                    params = city;
                    placeNameLookup = city;
                }else{
                    params = `${city}+${state}`;
                    placeNameLookup = `${city} ${state}`;
                }
                lookupFunc = apiCalls.placeNameLookup;
            }

            lookupFunc (params,  (error, result, duration) => {

                if(error || result === null) {
                    // API Call failed or result is null 
                    speechOutput = speech.getSpeechText('error2', false);
                    repromtText = speech.getSpeechText('reprompt3', false);

                    return handlerInput.responseBuilder
                    .speak(speechOutput)
                    .reprompt(repromtText)
                    .withSimpleCard(cardTitle, speechOutput)
                    .withShouldEndSession(false)
                    .getResponse();
                }else if (Object.keys(result).length === 0) {
                    // Returned an empty result
                    if (zipcode.length > 0) {
                        // was zipcode 
                        let speechObject = speech.getSpeechObject('setdefaultloc4');
                        repromtText = speech.getSpeechText('reprompt3', false);


                        speechOutput = util.format(speechObject.text, zipcode);

                    }else{
                        // wasn't zipcode
                        let speechObject = speech.getSpeechObject('setdefaultloc3');

                        repromtText = speech.getSpeechText('reprompt3', false);

                        speechOutput = util.format(speechObject.text, zipcode);

                    }
                    return handlerInput.responseBuilder
                        .speak(speechOutput)
                        .reprompt(repromtText)
                        .withSimpleCard(cardTitle, speechOutput)
                        .withShouldEndSession(false)
                        .getResponse();
                }else {
                    // Api Call successfull with result objects length > 0
                    return new Promise( (resolve, reject) => {
                        handlerInput.attributesManager.getPersistentAttributes()
                            .then((attributes) => {
                                const defaultLoc = {
                                    name: result.name,
                                    lat: result.lat,
                                    lon: result.lon
                                };
                                const userId = handlerInput.requestEnvelope.context.System.user.userId;
                                attributes['defaultLoc'] = defaultLoc;

                                debugLog("Writing attributes to DynamoDB: " + userId + ", " + "defaultlocation: " + JSON.stringify(defaultLoc));
                                handlerInput.attributesManager.setSessionAttributes(attributes);
                                handlerInput.attributesManager.setPersistentAttributes(attributes);
                                handlerInput.attributesManager.savePersistentAttributes();

                                let speechObject = speech.getSpeechObject('setdefaultloc22');
                                repromtText = speech.getSpeechText('reprompt3', false);

                                speechOutput = util.format(speechObject.text, zipcode);

                                debugLog(`SpeechOutput After saving user location: ${speechOutput}`);

                                debugLog(`handlerInput: ${handlerInput.responseBuilder
                                    .speak(speechOutput)
                                    .reprompt(repromtText)
                                    .withShouldEndSession(false)
                                    .getResponse()}`);

                            resolve(handlerInput.responseBuilder.speak(speechOutput)
                                .reprompt(repromtText)
                                .withShouldEndSession(false)
                                .getResponse());
                            })
                            .catch((error) => {
                                console.log(`Error in SetDefaultLocationIntent promise: ${error}`);
                                reject(error);
                            });
                    });

                }
            });
        }

      },
  };

Finally solved the problem: It was merely a promise issue I wasn't handling properly , I had to wrap everything in the else statement in a promise and this is how I restructured the last else statement to get the desired result.

else {
            return new Promise((resolve, reject) => {
                let params = '';
                let lookupFunc = '';
                let placeNameLookup = '';
                if (zipcode.length > 0 && zipCodeValidator(zipcode)) {
                    params = zipcode;
                    lookupFunc = apiCalls.zipcodeLookup;
                }else {
                    if (state.length === 0) {
                        params = city;
                        placeNameLookup = city;
                    }else{
                        params = `${city}+${state}`;
                        placeNameLookup = `${city} ${state}`;
                    }
                    lookupFunc = apiCalls.placeNameLookup;
                }

                    lookupFunc (params,  (error, result, duration) => {

                        if(error || result === null) {
                            // API Call failed or result is null 
                            speechOutput = speech.getSpeechText('error2', false);
                            repromtText = speech.getSpeechText('reprompt3', false);

                             resolove(handlerInput.responseBuilder
                                .speak(speechOutput)
                                .reprompt(repromtText)
                                .withSimpleCard(cardTitle, speechOutput)
                                .withShouldEndSession(false)
                                .getResponse());
                        }else if (Object.keys(result).length === 0) {
                            // Returned an empty result
                            if (zipcode.length > 0) {
                                // was zipcode 
                                let speechObject = speech.getSpeechObject('setdefaultloc4');
                                repromtText = speech.getSpeechText('reprompt3', false);


                                speechOutput = util.format(speechObject.text, zipcode);

                            }else{
                                // wasn't zipcode
                                let speechObject = speech.getSpeechObject('setdefaultloc3');

                                repromtText = speech.getSpeechText('reprompt3', false);

                                speechOutput = util.format(speechObject.text, zipcode);

                            }
                            resolve(handlerInput.responseBuilder
                                .speak(speechOutput)
                                .reprompt(repromtText)
                                .withSimpleCard(cardTitle, speechOutput)
                                .withShouldEndSession(false)
                                .getResponse());
                        }else {
                            // Api Call successfull with result objects length > 0
                                handlerInput.attributesManager.getPersistentAttributes()
                                    .then((attributes) => {
                                        const defaultLoc = {
                                            name: result.name,
                                            lat: result.lat,
                                            lon: result.lon
                                        };
                                        const userId = handlerInput.requestEnvelope.context.System.user.userId;
                                        attributes['defaultLoc'] = defaultLoc;

                                        debugLog("Writing attributes to DynamoDB: " + userId + ", " + "defaultlocation: " + JSON.stringify(defaultLoc));
                                        handlerInput.attributesManager.setSessionAttributes(attributes);
                                        handlerInput.attributesManager.setPersistentAttributes(attributes);
                                        handlerInput.attributesManager.savePersistentAttributes();

                                        let speechObject = speech.getSpeechObject('setdefaultloc22');
                                        repromtText = speech.getSpeechText('reprompt3', false);

                                        speechOutput = util.format(speechObject.text, zipcode);

                                        debugLog(`SpeechOutput After saving user location: ${speechOutput}`);

                                        debugLog(`handlerInput: ${handlerInput.responseBuilder}`);

                                        resolve(handlerInput.responseBuilder.speak(speechOutput)
                                            .reprompt(repromtText)
                                            .withShouldEndSession(false)
                                            .getResponse());
                                    })
                                    .catch((error) => {
                                        console.log(`Error in SetDefaultLocationIntent promise: ${error}`);
                                        reject(error);
                                    });

                        }
                    });

            });        
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM