簡體   English   中英

是否可以將回調內部的數據傳遞給其包裝函數?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM