Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Nodejs bày tỏ và hứa sẽ không làm những gì tôi mong đợi

Vấn đề với mã

Được rồi, có rất nhiều vấn đề ở đây nên trước tiên hãy làm.

        connection.query('...', function (err, rows) {
            connection.release();
            if (!err) {
                return rows;
            } else {
                return false;
            }
        });

Điều này sẽ không hoạt động vì bạn đang trả lại dữ liệu cho trình gọi, là truy vấn cơ sở dữ liệu gọi lại cuộc gọi của bạn với errrows và không quan tâm đến giá trị trả về của lệnh gọi lại của bạn.

Những gì bạn cần làm là gọi một số hàm hoặc phương thức khác khi bạn có các hàng hoặc khi bạn không có.

Bạn đang gọi:

var rows = loginM.findUser(req.body, res);

và bạn mong đợi để có được các hàng ở đó, nhưng bạn sẽ không. Những gì bạn sẽ nhận được là undefined và bạn sẽ nhận được nó nhanh hơn so với truy vấn cơ sở dữ liệu thậm chí được bắt đầu. Nó hoạt động như thế này:

me.findUser = function(params, res) {
    // (1) you save the username in a variable
    var username = params.username;

    // (2) you pass a function to getConnection method
    pool.getConnection(function (err, connection) {
        console.log("Connection ");

        if (err) {
            console.log("ERROR 1 ");
            res.send({"code": 100, "status": "Error in connection database"});
            return;
        }

        connection.query('select Id, Name, Password from Users ' +
            'where Users.Name = ?', [username], function (err, rows) {
            connection.release();
            if (!err) {
                return rows;
            } else {
                return false;
            }
        });

        //connection.on('error', function (err) {
        //    res.send({"code": 100, "status": "Error in connection database"});
        //    return;
        //});
    });

    // (3) you end a function and implicitly return undefined
}

pool.getConnection phương thức trả về ngay lập tức sau khi bạn truyền một hàm, trước khi kết nối với cơ sở dữ liệu được thực hiện. Sau đó, sau một thời gian, hàm mà bạn đã chuyển cho phương thức đó có thể được gọi, nhưng sẽ rất lâu sau khi bạn trả về undefined đến mã muốn có giá trị trong:

var rows = loginM.findUser(req.body, res);

Thay vì trả về giá trị từ các lệnh gọi lại, bạn cần gọi một số hàm hoặc phương thức khác từ chúng (như một số lệnh gọi lại mà bạn cần gọi hoặc một phương thức để giải quyết một lời hứa).

Trả về giá trị là một khái niệm đồng bộ và sẽ không hoạt động đối với mã không đồng bộ.

Nên sử dụng lời hứa như thế nào

Bây giờ, nếu hàm của bạn trả về một lời hứa :

me.findUser = function(params, res) {
    var username = params.username;

    return new Promise(function (res, rej) {

      pool.getConnection(function (err, connection) {
        console.log("Connection ");

        if (err) {
          rej('db error');
        } else {
          connection.query('...', [username], function (err, rows) {
            connection.release();
            if (!err) {
                res(rows);
            } else {
                rej('other error');
            }
        });
      });
    });
}

thì bạn sẽ có thể sử dụng nó trong một số phần khác của mã theo cách như sau:

app.post('/login/', function(req, res, next) {

    var promise = new Promise(function (resolve, reject) {

        // rows is a promise now:
        var rows = loginM.findUser(req.body, res);

        rows.then(function (rowsValue) {
            console.log("Success");
            resolve(rowsValue);
        }).catch(function (err) {
            console.log("Failed");
            reject(err);
        });
    });
    // ...

Giải thích

Tóm lại, nếu bạn đang chạy một hoạt động không đồng bộ - như truy vấn cơ sở dữ liệu - thì bạn không thể có giá trị ngay lập tức như sau:

var value = query();

bởi vì máy chủ sẽ cần phải chặn chờ cơ sở dữ liệu trước khi nó có thể thực hiện nhiệm vụ - và đây là điều xảy ra trong mọi ngôn ngữ có I / O đồng bộ, chặn (đó là lý do tại sao bạn cần có các luồng trong các ngôn ngữ đó để những thứ khác có thể được thực hiện trong khi luồng đó bị chặn).

Trong Node, bạn có thể sử dụng một hàm gọi lại mà bạn chuyển cho hàm không đồng bộ để được gọi khi nó có dữ liệu:

query(function (error, data) {
  if (error) {
    // we have error
  } else {
    // we have data
  }
});
otherCode();

Hoặc bạn có thể nhận được một lời hứa:

var promise = query();
promise.then(function (data) {
  // we have data
}).catch(function (error) {
  // we have error
});
otherCode();

Nhưng trong cả hai trường hợp otherCode() sẽ được chạy ngay lập tức sau khi đăng ký trình xử lý gọi lại hoặc hứa hẹn của bạn, trước khi truy vấn có bất kỳ dữ liệu nào - điều đó không cần phải thực hiện chặn.

Tóm tắt

Toàn bộ ý tưởng là trong một môi trường không đồng bộ, không chặn, đơn luồng như Node.JS, bạn không bao giờ làm nhiều việc cùng một lúc - nhưng bạn có thể chờ đợi rất nhiều thứ. Nhưng bạn không chỉ chờ đợi một điều gì đó và không làm gì trong khi chờ đợi, bạn lên lịch cho những việc khác, chờ đợi nhiều thứ hơn và cuối cùng bạn sẽ được gọi lại khi nó đã sẵn sàng.

Thực ra tôi đã viết một truyện ngắn trên Medium để minh họa cho khái niệm đó: I / O không ngừng nghỉ trên hành tinh Asynchronia256 / 16 - Một câu chuyện ngắn dựa trên những sự kiện không chắc chắn .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách thêm ràng buộc not null vào cột hiện có trong MySQL

  2. Sắp xếp thứ tự theo giá trị trường cụ thể trước tiên

  3. Tạo một chỉ mục trên một bảng sản xuất MySQL khổng lồ mà không cần khóa bảng

  4. mySQL - Tạo một bảng mới bằng cách sử dụng dữ liệu và cột từ ba bảng

  5. Cách sử dụng các chỉ mục để cải thiện hiệu suất truy vấn MySQL