[英]Is it possible to pass data inside a callback to its wrapped function?
我正在創建用戶登錄系統,需要查詢數據庫。 我是編碼的新手,我正努力理解回調以及回調發生后如何傳遞數據。
我有一個通過回調調用的MySQL查詢。 結果,我需要在下面的異步函數體中使用,以作為在app.js中的使用。 異步功能位於路由文件中。
我嘗試在回調范圍之外創建變量,正如您在此處看到的那樣,在.query()
之前聲明了用戶,但在運行之后我仍然收到undefined
。 我也嘗試過在connection.query之前使用關鍵字await
,因此該函數直到回調完成后才運行,但這似乎也不起作用。
由於我仍在嘗試了解JS的工作原理,因此在此刻的任何幫助將不勝感激。 謝謝
async function getAll() {
var users;
var query = "SELECT * FROM `users`"; // query database to get
all the players
// execute query
connection.query(query, (err, result) => {
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
users = result;
});
return users.map(u => {
const { password, ...userWithoutPassword } = u;
return userWithoutPassword;
});
}
下面的函數是在app.js中調用異步函數的地方:
function getAll(req, res, next) {
userService.getAll().then(users => {
console.log(users);
res.json(users)}).catch(err => next(err));
}
您沒有顯示正在使用的一堆變量,這使我認為您可能使用了不正確的變量。 在異步代碼(服務器上的特定異步代碼)中,不應使用共享或全局變量來處理特定的請求處理程序。 如果這樣做,您將為並發問題敞開心yourself,其中兩個請求相互沖突。 這將在服務器中創建很難發現和調試的錯誤。
在Javascript異步回調中,您可以在回調內部繼續執行邏輯流程,因為這是您唯一了解數據值和響應時間的地方。 您無需將其分配給更高級別的變量,然后以某種方式在其他范圍內使用該數據。 這永遠不會起作用,因為只有在回調函數內部您才能確切知道該數據何時有效。
另外,僅當您實際上打算在函數內部使用帶有promise的await
時,才需要將函數標記為async
,因此在這種情況下,由於您根本沒有在數據庫中使用promise,因此沒有真正原因使函數async
。
如果您向我們展示此getAll()
函數如何適合整個請求處理程序的更大上下文,我們可以幫助您更好地設計事物,但是我至少已更改了函數以傳遞res
以便可以在錯誤案例和成功案例都可以發送響應。
這是一個總體思路:
// method of userService
function getAll(res) {
var query = "SELECT * FROM `users`"; // query database to get all the players
// execute query
connection.query(query, (err, result) => {
if (err) {
res.redirect('error.ejs');
console.log(error.message);
} else {
// do something here to process result from your query
let users = result.map(u => {
// not sure what you're trying to do here
return u.userWithoutPassword;
});
// do something with users here
res.send(...);
}
});
// no code here because this will run BEFORE your query is done
}
// change to pass req to userService.getAll(res)
function getAll(req, res, next) {
userService.getAll(res);
}
如果要從getAll()
傳遞回一個值或成功/錯誤,則需要傳遞一個可以調用的回調,或者需要返回一個Promise,可以使用已解析的值進行回傳。價值。
如果您想了解有關返回異步值的更多信息,請參見以下答案: 如何返回異步調用的響應?
我的建議是基於承諾。 mysql2庫具有對Promise的內置支持,您需要將它們切換為專用而不是mysql庫。 對於錯誤的發送或成功的響應,我也將完全一致:
const msql = require("mysql2/promise");
// userService.getAll()
async function getAll() {
var users;
var query = "SELECT * FROM `users`"; // query database to get all the players
let result = await connection.query(query);
return result.map(u => {
const {
password,
...userWithoutPassword
} = u;
return userWithoutPassword;
});
}
// request handler
function getAll(req, res, next) {
userService.getAll().then(users => {
console.log(users);
res.json(users);
}).catch(err => {
console.log(error.message);
res.redirect('error.ejs');
});
})
好的,我想我終於可以僅使用回調來解決我的問題了。 如果有人可以幫助我,現在最好將其發展為使用諾言。 但是這是我的最終產品(隨意拆開):
grabUsers()
函數啟動查詢,然后將數據傳遞到回調函數中,以在下一個回調中使用。
function grabUsers(callback){
var query = "SELECT * FROM `users`"; // query database to get all the
players
// execute query
connection.query(query, (err, result) => {
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
let users = result;
callback(null, users);
})
}
然后,getAll函數使用grabUsers()
回調來處理數據。
function getAll(callback) {
grabUsers(function(err, users){
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
users = users.map(u => {
const { password, ...userWithoutPassword } = u;
return userWithoutPassword;
});
callback(null, users);
});
}
然后,app.js上的最終getAll函數會對代碼進行最后的填充,而無需使用回調參數,因為這是鏈中函數的最底層。
function getAll(req, res, next) {
userService.getAll(function(err,users){
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
res.json(users);
console.log(users);
})
希望這可以幫助其他人在回調和數據上苦苦掙扎。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.