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 err
và rows
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 .