Node.js 中的回调:两个不同代码片段的比较
Callbacks in Node.js: Comparison of two different code snippets
我一直在 Node.js 中使用回调进行一些工作,致力于 Messenger 机器人。
我写了一个函数来提取用户的名字并将其传递给另一个函数。我需要向该函数添加回调以使其正常工作。我获取用户名的函数如下所示:
function getFBUserName(callback)
{
let graphURL = 'https://graph.facebook.com/v2.6/';
let graphFields = '?fields=first_name,last_name,gender';
let graphToken = '&access_token=';
let reqURL = graphURL + usrPSID + graphFields + graphToken + config.FB_PAGE_ACCESS_TOKEN;
let reqJSON;
request(reqURL, function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response
// status code if a response was received
console.log(body);
reqJSON = JSON.parse(body);
if (reqJSON.hasOwnProperty("first_name")){
console.log("First Name exists"); // Debugging, to see if hasOwnProperty is working
let userName = reqJSON['first_name'];
callback(userName);
}
});
}
此函数然后将回调传递给我的 handlePostback() 函数:
function handlePostback(sender_psid, received_postback) {
let response;
let responseText;
// Get the payload for the postback
let payload = received_postback.payload;
// Set the response based on the postback payload
if (payload === 'GET_STARTED') {
let userName;
getFBUserName(function (uName) {
userName = uName;
responseText = "Hi there " + userName + ", welcome to the bot!";
response = {"text": responseText};
callSendAPI(sender_psid, response);
});
}
}
上面的代码有效。但是如果我更改我的代码使其看起来像下面这样,它就不起作用。 userName 变量始终未定义。
function handlePostback(sender_psid, received_postback) {
let response;
let responseText;
// Get the payload for the postback
let payload = received_postback.payload;
// Set the response based on the postback payload
if (payload === 'GET_STARTED') {
let userName;
getFBUserName(function (uName) {
userName = uName;
});
responseText = "Hi there " + userName + ", welcome to the bot!";
}
response = {"text": responseText};
callSendAPI(sender_psid, response);
}
我想使用第二种代码结构,因为当我向我的 if 语句添加回发时,将会有很多重复的代码。在 if 语句中为回发设置 responseText 是有意义的,然后设置响应并在循环外发送消息。所以我的问题是,为什么第一个结构起作用,而第二个结构不起作用?
问题是 getFBUserName
是一个异步函数,它在完成时执行回调,因此 getFBUseName
调用下面的行可能在回调之前执行。
尝试执行这段代码,您可能会更好地理解什么是回调。
setTimeout(function () {
console.log('Callback function')
}, 500)
console.log('This is called first!')
回调函数传给了setTimeout,setTimeout(callback, timeInMillisecons)
所以在那个时间之后执行,另一个console.log
在之前执行
这是一个愚蠢的例子,但当您向 API(例如 Facebook API)发出请求时,情况也是如此。您不知道请求需要多长时间才能响应,但您希望在那之后执行一些代码,并使用您获取的数据。所以你可以使用回调。
我一直在 Node.js 中使用回调进行一些工作,致力于 Messenger 机器人。
我写了一个函数来提取用户的名字并将其传递给另一个函数。我需要向该函数添加回调以使其正常工作。我获取用户名的函数如下所示:
function getFBUserName(callback)
{
let graphURL = 'https://graph.facebook.com/v2.6/';
let graphFields = '?fields=first_name,last_name,gender';
let graphToken = '&access_token=';
let reqURL = graphURL + usrPSID + graphFields + graphToken + config.FB_PAGE_ACCESS_TOKEN;
let reqJSON;
request(reqURL, function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response
// status code if a response was received
console.log(body);
reqJSON = JSON.parse(body);
if (reqJSON.hasOwnProperty("first_name")){
console.log("First Name exists"); // Debugging, to see if hasOwnProperty is working
let userName = reqJSON['first_name'];
callback(userName);
}
});
}
此函数然后将回调传递给我的 handlePostback() 函数:
function handlePostback(sender_psid, received_postback) {
let response;
let responseText;
// Get the payload for the postback
let payload = received_postback.payload;
// Set the response based on the postback payload
if (payload === 'GET_STARTED') {
let userName;
getFBUserName(function (uName) {
userName = uName;
responseText = "Hi there " + userName + ", welcome to the bot!";
response = {"text": responseText};
callSendAPI(sender_psid, response);
});
}
}
上面的代码有效。但是如果我更改我的代码使其看起来像下面这样,它就不起作用。 userName 变量始终未定义。
function handlePostback(sender_psid, received_postback) {
let response;
let responseText;
// Get the payload for the postback
let payload = received_postback.payload;
// Set the response based on the postback payload
if (payload === 'GET_STARTED') {
let userName;
getFBUserName(function (uName) {
userName = uName;
});
responseText = "Hi there " + userName + ", welcome to the bot!";
}
response = {"text": responseText};
callSendAPI(sender_psid, response);
}
我想使用第二种代码结构,因为当我向我的 if 语句添加回发时,将会有很多重复的代码。在 if 语句中为回发设置 responseText 是有意义的,然后设置响应并在循环外发送消息。所以我的问题是,为什么第一个结构起作用,而第二个结构不起作用?
问题是 getFBUserName
是一个异步函数,它在完成时执行回调,因此 getFBUseName
调用下面的行可能在回调之前执行。
尝试执行这段代码,您可能会更好地理解什么是回调。
setTimeout(function () {
console.log('Callback function')
}, 500)
console.log('This is called first!')
回调函数传给了setTimeout,setTimeout(callback, timeInMillisecons)
所以在那个时间之后执行,另一个console.log
在之前执行
这是一个愚蠢的例子,但当您向 API(例如 Facebook API)发出请求时,情况也是如此。您不知道请求需要多长时间才能响应,但您希望在那之后执行一些代码,并使用您获取的数据。所以你可以使用回调。