我如何使用回调 return 来自 node.js 函数的值?
How do i return a value from a node.js function using a callback?
我是来自 vb.net 背景的 nodejs 新手。我看过很多使用回调的例子,但我就是不明白。很抱歉,如果这是非常基本的。
我正在编写一个 AWS Lambda 函数并尝试从 AWS IOT Thing Shadow 获取一个值并将其分配给一个变量。但是我无法让它工作,但是日志确实显示返回了该值。我知道它与 sync/async 有关,但不知道如何获得它。这是到目前为止的代码:
//determine doorstate
function getdoorstate() {
//ask the thing
var currentstate;
var paramsGet = {
"thingName": "garagedoor1",
};
iotData.getThingShadow(paramsGet, function (err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
console.log(data.payload);
var obj = JSON.parse(data.payload);
currentstate=obj["state"]["reported"]["doorstate"];
console.log("The function doorstate is: "+currentstate);
}
});
}
var doorstate = getdoorstate();
日志显示控制台写入正常(假设它们发生在检索到数据之后):
INFO {"state":{"desired":{"doorstate":0,"transitstate":0},"reported":{"doorstate":0,"transitstate":0}},"metadata":{"desired":{"doorstate":{"timestamp":1591241517},"transitstate":{"timestamp":1591241517}},"reported":{"doorstate":{"timestamp":1591241517},"transitstate":{"timestamp":1591241517}}},"version":444,"timestamp":1591241860}
The function doorstate is: 0
然而返回的值是:undefined
任何人都可以建议如何更改我的代码以正确使用回调。简单点——我是新来的!
谢谢!
根据 Sagar 建议的更新代码 - 仍然存在问题
//determine doorstate
function getdoorstate() {
//ask the thing
var paramsGet = {
"thingName": "garagedoor1",
};
iotData.getThingShadow(paramsGet, function (err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
callback(data)
}
});
}
getdoorstate(function (value){
console.log(value);
});
var doorstate = getdoorstate();
我又做错了什么?
getdoorState 函数有异步操作,如果你直接调用它,获取物联网的过程将在后台,它会开始执行下一行。
所以当你直接调用 getdoorstate() 时,它总是 return 未定义。您需要等待 api 调用以使用 callback, promises 或 async await
返回数据
你可以试试这样的
// using call back
function getdoorstate(callback) {
//ask the thing
iotData.getThingShadow(paramsGet, function (err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
callback(data)
}
});
}
getdoorstate(function (value){
console.log(value)
// Access value here
});
// Below line won't work
var value = getdoorstate()
// using promises
function getdoorstate(callback) {
return new Promise((resolve, reject) => {
//ask the thing
iotData.getThingShadow(paramsGet, function (err, data) {
if (err)
reject(err)
else
resolve(data)
});
}
})
getdoorstate()
.then(data => {
console.log(data)
})
.catch(err=>{
console.log(data)
})
基于 Sagar 的上述帮助,我现在已经能够在 nodejs 中了解回调、承诺和等待。 (好吧,反正我是这么认为的。)下面的代码片段现在是从我的 Lambda 函数中提取的一个工作示例。其余代码仅基于 Github 或 AWS 上可用的示例。
我的解决方案是对一部分使用回调,对 Alexa 处理程序代码中的代码使用 async/promise/await。这可能现在可以简化为更简单的代码,因此代码不会在每个处理程序中重复,但对于它的价值,我希望下面的代码能帮助其他一些 nodejs 和 AWS IOT/Alexa 的新手弄清楚如何获得Lamda 等待从物联网事物影子中获取所需的值。
// more code above ...(see ASK and AWS samples)
//IOT Stuff - settings
AWS.config.region = "<put your own region in here>";
var IOT_Data = new AWS.IotData({
endpoint: "<put your IOT Shadow Endpoint in here>"
});
var IOT_Thing = {
"thingName": "<put the name of your thing here>"
};
var doorstate; //this is used to hold the part of JSON data I want
//additional functions
//get shadow of thing using a call back. this function uses a nodejs callback
function getdoorstate(callback) {
IOT_Data.getThingShadow(IOT_Thing, function(err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
callback(data);
}
});
}
//..more code in here.. not shown in this snippet
//this is one of the Alexa intent handlers
// core functionality
const DoorStateHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
// checks request type - this one handes an intent with name of doorState
return request.type === 'IntentRequest' &&
request.intent.name === 'doorState';
},
// important to use the async here to get the code to wait for the 'promise' (uses nodejs promise and await)
async handle(handlerInput) {
var speakOutput = "Let me check..."; /set a var ready for the speech to send back to Alexa
//set up a promise so that we can get the value I need from the thing shadow
let promise = new Promise((resolve, reject) => {
getdoorstate(function(value) {
var obj = JSON.parse(value.payload); //parse to json
doorstate = obj["state"]["reported"]["doorstate"]; //return just the value of the doorstate
console.log("The doorstate is: " + doorstate);
speakOutput = speakOutput.concat(msg[doorstate]); //concatenate this to the var containing the speech
resolve(speakOutput); //resolve the promise and return the speech
});
});
//return result
// this is important - use the await here so that we dont proceed any further until the promise is resolved with the thing values
let result = await promise;
return handlerInput.responseBuilder
.speak(result)
.withSimpleCard("Garage Door", result)
.getResponse();
},
};
// this is another handler for sending a desired action to the IOT shadow
const DoorTransitHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
// checks request type
return request.type === 'IntentRequest' &&
request.intent.name === 'activate_door';
},
//again use async so that we can use promise and await - all the rest like above..
async handle(handlerInput) {
var speakOutput = "I'm on it...";
let promise = new Promise((resolve, reject) => {
getdoorstate(function(value) {
var obj = JSON.parse(value.payload);
doorstate = obj["state"]["reported"]["doorstate"];
console.log("The doorstate is: " + doorstate);
speakOutput = speakOutput.concat(msg[doorstate]);
resolve(speakOutput);
});
});
//return result
let result = await promise;
// set output
result += "I'll push the button for you. ";
//build the json to send back to the IOT shadow to get the thing to do something
var paramsUpdate = {
"topic": "$aws/things/garagedoor1/shadow/update",
"payload": '{"state":{"desired":{"doorstate":0,"transitstate":1}}}',
"qos": 0
};
//now here we send our desired action back to the IOT Thing Shadow
IOT_Data.publish(paramsUpdate, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data.payload); // successful response
});
// return response by means of Alexa
return handlerInput.responseBuilder
.speak(result)
.getResponse();
},
};
// and the code continues... (see ASK and AWS samples)
我是来自 vb.net 背景的 nodejs 新手。我看过很多使用回调的例子,但我就是不明白。很抱歉,如果这是非常基本的。
我正在编写一个 AWS Lambda 函数并尝试从 AWS IOT Thing Shadow 获取一个值并将其分配给一个变量。但是我无法让它工作,但是日志确实显示返回了该值。我知道它与 sync/async 有关,但不知道如何获得它。这是到目前为止的代码:
//determine doorstate
function getdoorstate() {
//ask the thing
var currentstate;
var paramsGet = {
"thingName": "garagedoor1",
};
iotData.getThingShadow(paramsGet, function (err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
console.log(data.payload);
var obj = JSON.parse(data.payload);
currentstate=obj["state"]["reported"]["doorstate"];
console.log("The function doorstate is: "+currentstate);
}
});
}
var doorstate = getdoorstate();
日志显示控制台写入正常(假设它们发生在检索到数据之后):
INFO {"state":{"desired":{"doorstate":0,"transitstate":0},"reported":{"doorstate":0,"transitstate":0}},"metadata":{"desired":{"doorstate":{"timestamp":1591241517},"transitstate":{"timestamp":1591241517}},"reported":{"doorstate":{"timestamp":1591241517},"transitstate":{"timestamp":1591241517}}},"version":444,"timestamp":1591241860}
The function doorstate is: 0
然而返回的值是:undefined
任何人都可以建议如何更改我的代码以正确使用回调。简单点——我是新来的! 谢谢!
根据 Sagar 建议的更新代码 - 仍然存在问题
//determine doorstate
function getdoorstate() {
//ask the thing
var paramsGet = {
"thingName": "garagedoor1",
};
iotData.getThingShadow(paramsGet, function (err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
callback(data)
}
});
}
getdoorstate(function (value){
console.log(value);
});
var doorstate = getdoorstate();
我又做错了什么?
getdoorState 函数有异步操作,如果你直接调用它,获取物联网的过程将在后台,它会开始执行下一行。
所以当你直接调用 getdoorstate() 时,它总是 return 未定义。您需要等待 api 调用以使用 callback, promises 或 async await
返回数据你可以试试这样的
// using call back
function getdoorstate(callback) {
//ask the thing
iotData.getThingShadow(paramsGet, function (err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
callback(data)
}
});
}
getdoorstate(function (value){
console.log(value)
// Access value here
});
// Below line won't work
var value = getdoorstate()
// using promises
function getdoorstate(callback) {
return new Promise((resolve, reject) => {
//ask the thing
iotData.getThingShadow(paramsGet, function (err, data) {
if (err)
reject(err)
else
resolve(data)
});
}
})
getdoorstate()
.then(data => {
console.log(data)
})
.catch(err=>{
console.log(data)
})
基于 Sagar 的上述帮助,我现在已经能够在 nodejs 中了解回调、承诺和等待。 (好吧,反正我是这么认为的。)下面的代码片段现在是从我的 Lambda 函数中提取的一个工作示例。其余代码仅基于 Github 或 AWS 上可用的示例。
我的解决方案是对一部分使用回调,对 Alexa 处理程序代码中的代码使用 async/promise/await。这可能现在可以简化为更简单的代码,因此代码不会在每个处理程序中重复,但对于它的价值,我希望下面的代码能帮助其他一些 nodejs 和 AWS IOT/Alexa 的新手弄清楚如何获得Lamda 等待从物联网事物影子中获取所需的值。
// more code above ...(see ASK and AWS samples)
//IOT Stuff - settings
AWS.config.region = "<put your own region in here>";
var IOT_Data = new AWS.IotData({
endpoint: "<put your IOT Shadow Endpoint in here>"
});
var IOT_Thing = {
"thingName": "<put the name of your thing here>"
};
var doorstate; //this is used to hold the part of JSON data I want
//additional functions
//get shadow of thing using a call back. this function uses a nodejs callback
function getdoorstate(callback) {
IOT_Data.getThingShadow(IOT_Thing, function(err, data) {
if (err) {
console.log("Error : " + err, err.stack);
} else {
callback(data);
}
});
}
//..more code in here.. not shown in this snippet
//this is one of the Alexa intent handlers
// core functionality
const DoorStateHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
// checks request type - this one handes an intent with name of doorState
return request.type === 'IntentRequest' &&
request.intent.name === 'doorState';
},
// important to use the async here to get the code to wait for the 'promise' (uses nodejs promise and await)
async handle(handlerInput) {
var speakOutput = "Let me check..."; /set a var ready for the speech to send back to Alexa
//set up a promise so that we can get the value I need from the thing shadow
let promise = new Promise((resolve, reject) => {
getdoorstate(function(value) {
var obj = JSON.parse(value.payload); //parse to json
doorstate = obj["state"]["reported"]["doorstate"]; //return just the value of the doorstate
console.log("The doorstate is: " + doorstate);
speakOutput = speakOutput.concat(msg[doorstate]); //concatenate this to the var containing the speech
resolve(speakOutput); //resolve the promise and return the speech
});
});
//return result
// this is important - use the await here so that we dont proceed any further until the promise is resolved with the thing values
let result = await promise;
return handlerInput.responseBuilder
.speak(result)
.withSimpleCard("Garage Door", result)
.getResponse();
},
};
// this is another handler for sending a desired action to the IOT shadow
const DoorTransitHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
// checks request type
return request.type === 'IntentRequest' &&
request.intent.name === 'activate_door';
},
//again use async so that we can use promise and await - all the rest like above..
async handle(handlerInput) {
var speakOutput = "I'm on it...";
let promise = new Promise((resolve, reject) => {
getdoorstate(function(value) {
var obj = JSON.parse(value.payload);
doorstate = obj["state"]["reported"]["doorstate"];
console.log("The doorstate is: " + doorstate);
speakOutput = speakOutput.concat(msg[doorstate]);
resolve(speakOutput);
});
});
//return result
let result = await promise;
// set output
result += "I'll push the button for you. ";
//build the json to send back to the IOT shadow to get the thing to do something
var paramsUpdate = {
"topic": "$aws/things/garagedoor1/shadow/update",
"payload": '{"state":{"desired":{"doorstate":0,"transitstate":1}}}',
"qos": 0
};
//now here we send our desired action back to the IOT Thing Shadow
IOT_Data.publish(paramsUpdate, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data.payload); // successful response
});
// return response by means of Alexa
return handlerInput.responseBuilder
.speak(result)
.getResponse();
},
};
// and the code continues... (see ASK and AWS samples)