未调用 Amazon Alexa 技能回调
Amazon Alexa Skill Callback not being called
我有一个 Alexa 技能,可以获取设备的地址并使用该信息找到附近的设施。
我看过@jfriend00 提出的解决方案here。我的回调的结构相同。我仍然不明白为什么在其余代码运行之前我的回调没有返回。我应该从 getJSON()
的回调中看到 console.info()
调用,但它从未运行过。
编辑: 我显然不明白这种异步的东西是如何工作的,因为我的日志完全不正常。有人可以向我解释发生了什么事吗?我查看了我链接的解决方案,我的代码看起来与他的准系统解决方案尽可能相似。我不明白我哪里错了。
控制台日志
getKaiserBuildingHandler()
const getKaiserBuildingHandler = function() {
console.info("Starting getKaiserBuildingHandler()");
...
switch(addressResponse.statusCode) {
case 200:
console.log("Address successfully retrieved, now responding to user.");
const addressObj = addressResponse.address;
const address = `${addressObj['addressLine1']}, ${addressObj['city']}, ${addressObj['stateOrRegion']} ${addressObj['postalCode']}`;
var ADDRESS_MESSAGE = Messages.ADDRESS_AVAILABLE;
const alexa = this;
getKaiserBuildingHelper(buildingType, address, function(response) {
ADDRESS_MESSAGE += response;
alexa.emit(":tell", ADDRESS_MESSAGE);
console.info("Ending getKaiserBuildingHandler()");
});
break;
...
}
});
...
};
getKaiserBuildingHelper()
const getKaiserBuildingHelper = function(buildingType, address, callback) {
console.info("Starting getKaiserBuildingHelper()");
// var facilityOutput = Messages.ERROR;
var facilityOutput = "Inside building helper function, initial value.";
if (buildingType == BLDG_TYPE.PHARMACY ||
buildingType == BLDG_TYPE.CLINIC ||
buildingType == BLDG_TYPE.HOSPITAL) {
...
facilityOutput = "Before get JSON call.";
getJSON(buildingType, function(err, data) {
if (data != "ERROR") {
console.info("Received data from callback: ", data);
facilityOutput = "The closest Kaiser Permanente " + buildingType + " to your location is located at " + data + ".";
} else {
console.error("Error with data received from callback. ", err);
facilityOutput = "Entered JSON call, returned ERROR.";
}
});
}
...
callback(facilityOutput);
console.info("Ending getKaiserBuildingHelper()");
}
getJSON()
const getJSON = function(building, callback) {
console.info("Starting getJSON()");
Axios
.get(getFacilitySearchEndpoint(building))
.then(function(response) {
const responseData = response.data.query.search[0].title;
callback(null, responseData);
console.info("Data retrieved from Axios call");
console.info("Ending getJSON()");
})
.catch(function(error) {
callback(error, "ERROR");
console.info("Error caught from Axios call");
console.info("Ending getJSON()");
});
}
getFacilitySearchEndpoint() [维基百科 api 就像占位符]
const getFacilitySearchEndpoint = function(building) {
console.info("Starting getFacilitySearchEndpoint()");
switch (building) {
case BLDG_TYPE.HOSPITAL:
console.info("Ending getFacilitySearchEndpoint() with " + building);
return "https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&utf8=1&srsearch=Albert+Einstein";
break;
case BLDG_TYPE.PHARMACY:
console.info("Ending getFacilitySearchEndpoint() with " + building);
return "https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&utf8=1&srsearch=Harry+Potter";
break;
case BLDG_TYPE.CLINIC:
console.info("Ending getFacilitySearchEndpoint() with " + building);
return "https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&utf8=1&srsearch=Tony+Stark";
break;
default:
console.info("Ending getFacilitySearchEndpoint() with default");
break;
}
console.info("Ending getFacilitySearchEndpoint()");
}
我在聊天中留下了一些笔记,但这里的内容可能更清楚。一定要再看一下 Felix 在您提供的 link 中的回答,但是由于您在这里有很多代码,所以如果我在那个上下文中进行解释会更容易理解。
Axios.get
是异步的,这意味着它实际上 returns 在 HTTP 请求完成之前。因此,getJSON
主体中在您发出请求后发生的任何事情,实际上都会在传递给 then
或 catch
的函数被调用之前发生:
function getJSON (url, callback) {
Axios
.get(url)
.then(function (data) {
console.log('I happen later, when the request is finished')
callback(null, data)
})
.catch(function (err) {
console.log('I happen later, only if there was an error')
callback(err)
})
console.log('I happen immediately!')
}
很容易混淆——在异步代码中,事情不一定按照它们在代码中出现的顺序发生。所以我们在调用异步函数的时候要注意这一点。
这意味着 getKaiserBuildingHelper
函数内部有问题。因为您的 getJSON
函数只是 Axios promise 的回调式包装器,所以它也是异步的。它会立即return,在请求完成之前,函数体内的其余代码将照常继续运行。
function getKaiserBuildingHelper (callback) {
let facilityOutput = 'initial value'
getJSON('http://some-url.com', function (err, data) {
console.log('I happen later, when the request is complete')
if (err) {
facilityOutput = 'Error!'
} else {
facilityOutput = 'Success!'
}
})
console.log('I happen immediately!')
callback(facilityOutput)
}
这意味着最后一行 callback(facilityOutput)
发生在 getJSON
回调之前。结果,facilityOutput
的值保持不变。但是您可以通过将回调移动到 getJSON
回调中来轻松解决此问题:
function getKaiserBuildingHelper (callback) {
getJSON('http://some-url.com', function (err, data) {
if (err) {
callback('Error!')
} else {
callback('Success!')
}
})
}
现在您可以按预期使用函数了:
getKaiserBuildingHelper(function (message) {
console.log(message) // => 'Success!' or 'Error!'
}
最后,我不确定您为什么将 this.emit
添加到该回调。那是从别处复制粘贴的东西吗?
我有一个 Alexa 技能,可以获取设备的地址并使用该信息找到附近的设施。
我看过@jfriend00 提出的解决方案here。我的回调的结构相同。我仍然不明白为什么在其余代码运行之前我的回调没有返回。我应该从 getJSON()
的回调中看到 console.info()
调用,但它从未运行过。
编辑: 我显然不明白这种异步的东西是如何工作的,因为我的日志完全不正常。有人可以向我解释发生了什么事吗?我查看了我链接的解决方案,我的代码看起来与他的准系统解决方案尽可能相似。我不明白我哪里错了。
控制台日志
getKaiserBuildingHandler()
const getKaiserBuildingHandler = function() {
console.info("Starting getKaiserBuildingHandler()");
...
switch(addressResponse.statusCode) {
case 200:
console.log("Address successfully retrieved, now responding to user.");
const addressObj = addressResponse.address;
const address = `${addressObj['addressLine1']}, ${addressObj['city']}, ${addressObj['stateOrRegion']} ${addressObj['postalCode']}`;
var ADDRESS_MESSAGE = Messages.ADDRESS_AVAILABLE;
const alexa = this;
getKaiserBuildingHelper(buildingType, address, function(response) {
ADDRESS_MESSAGE += response;
alexa.emit(":tell", ADDRESS_MESSAGE);
console.info("Ending getKaiserBuildingHandler()");
});
break;
...
}
});
...
};
getKaiserBuildingHelper()
const getKaiserBuildingHelper = function(buildingType, address, callback) {
console.info("Starting getKaiserBuildingHelper()");
// var facilityOutput = Messages.ERROR;
var facilityOutput = "Inside building helper function, initial value.";
if (buildingType == BLDG_TYPE.PHARMACY ||
buildingType == BLDG_TYPE.CLINIC ||
buildingType == BLDG_TYPE.HOSPITAL) {
...
facilityOutput = "Before get JSON call.";
getJSON(buildingType, function(err, data) {
if (data != "ERROR") {
console.info("Received data from callback: ", data);
facilityOutput = "The closest Kaiser Permanente " + buildingType + " to your location is located at " + data + ".";
} else {
console.error("Error with data received from callback. ", err);
facilityOutput = "Entered JSON call, returned ERROR.";
}
});
}
...
callback(facilityOutput);
console.info("Ending getKaiserBuildingHelper()");
}
getJSON()
const getJSON = function(building, callback) {
console.info("Starting getJSON()");
Axios
.get(getFacilitySearchEndpoint(building))
.then(function(response) {
const responseData = response.data.query.search[0].title;
callback(null, responseData);
console.info("Data retrieved from Axios call");
console.info("Ending getJSON()");
})
.catch(function(error) {
callback(error, "ERROR");
console.info("Error caught from Axios call");
console.info("Ending getJSON()");
});
}
getFacilitySearchEndpoint() [维基百科 api 就像占位符]
const getFacilitySearchEndpoint = function(building) {
console.info("Starting getFacilitySearchEndpoint()");
switch (building) {
case BLDG_TYPE.HOSPITAL:
console.info("Ending getFacilitySearchEndpoint() with " + building);
return "https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&utf8=1&srsearch=Albert+Einstein";
break;
case BLDG_TYPE.PHARMACY:
console.info("Ending getFacilitySearchEndpoint() with " + building);
return "https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&utf8=1&srsearch=Harry+Potter";
break;
case BLDG_TYPE.CLINIC:
console.info("Ending getFacilitySearchEndpoint() with " + building);
return "https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&utf8=1&srsearch=Tony+Stark";
break;
default:
console.info("Ending getFacilitySearchEndpoint() with default");
break;
}
console.info("Ending getFacilitySearchEndpoint()");
}
我在聊天中留下了一些笔记,但这里的内容可能更清楚。一定要再看一下 Felix 在您提供的 link 中的回答,但是由于您在这里有很多代码,所以如果我在那个上下文中进行解释会更容易理解。
Axios.get
是异步的,这意味着它实际上 returns 在 HTTP 请求完成之前。因此,getJSON
主体中在您发出请求后发生的任何事情,实际上都会在传递给 then
或 catch
的函数被调用之前发生:
function getJSON (url, callback) {
Axios
.get(url)
.then(function (data) {
console.log('I happen later, when the request is finished')
callback(null, data)
})
.catch(function (err) {
console.log('I happen later, only if there was an error')
callback(err)
})
console.log('I happen immediately!')
}
很容易混淆——在异步代码中,事情不一定按照它们在代码中出现的顺序发生。所以我们在调用异步函数的时候要注意这一点。
这意味着 getKaiserBuildingHelper
函数内部有问题。因为您的 getJSON
函数只是 Axios promise 的回调式包装器,所以它也是异步的。它会立即return,在请求完成之前,函数体内的其余代码将照常继续运行。
function getKaiserBuildingHelper (callback) {
let facilityOutput = 'initial value'
getJSON('http://some-url.com', function (err, data) {
console.log('I happen later, when the request is complete')
if (err) {
facilityOutput = 'Error!'
} else {
facilityOutput = 'Success!'
}
})
console.log('I happen immediately!')
callback(facilityOutput)
}
这意味着最后一行 callback(facilityOutput)
发生在 getJSON
回调之前。结果,facilityOutput
的值保持不变。但是您可以通过将回调移动到 getJSON
回调中来轻松解决此问题:
function getKaiserBuildingHelper (callback) {
getJSON('http://some-url.com', function (err, data) {
if (err) {
callback('Error!')
} else {
callback('Success!')
}
})
}
现在您可以按预期使用函数了:
getKaiserBuildingHelper(function (message) {
console.log(message) // => 'Success!' or 'Error!'
}
最后,我不确定您为什么将 this.emit
添加到该回调。那是从别处复制粘贴的东西吗?