我遇到了异步调用的一些问题,但在理解了Node中的事件驱动函数之后,我有以下代码。它基本上做了2个SQL查询。首先检查表中是否有现有的电话号码。如果有,没有任何反应。如果没有,则运行第二个查询以向表中添加新值。
目前它是事件驱动的,但是..我如何重新设计它以便外部函数查询是一个单独的函数,甚至可以用作其他地方代码的验证检查? (基本上把它变成通用的辅助函数)?
router.post('/', function(req, res){
var mysql = req.app.get('mysql');
//values for 1st query - initial check
var customerCheck = "SELECT phone_number FROM customer WHERE phone_number=?";
var phoneNumberCheck = [req.body.phone_number];
//values for after 1st query validation passes
var sql = "INSERT INTO customer (name, phone_number, points, is_activated) VALUES (?,?,?,?)";
var inserts = [req.body.name, req.body.phone_number, 0, true];
mysql.pool.query(customerCheck, phoneNumberCheck, function(error, results, fields){
if(error){
console.log("Failed to verify!");
res.write(JSON.stringify(error));
res.end();
}else{
console.log(results);
if(results.length){
console.log("phone number exists, not adding.");
res.redirect('/view_customers');
}else{
mysql.pool.query(sql,inserts,function(error, results, fields){
if(error){
console.log("Failed to insert customer to DB!");
res.write(JSON.stringify(error));
res.end();
}else{
res.redirect('/view_customers');
}
});
}
}
});
});
答案 0 :(得分:1)
这是一种更有条理的方式,当然可以改进,但我把它留给你。
我添加了一个客户类,您可以在其中拥有check
和insert
个功能,现在您可以单独使用它们。
我将数据库查询包装在一个承诺中,以避免回调地狱(Learn how to avoid it here)
最后,路由器功能变得非常简单易读。
<强> customer.js 强>
class Customer {
constructor(mysql) {
this.mysql = mysql;
}
async check(number) {
const statement = 'SELECT phone_number FROM customer WHERE phone_number=?';
const results = await this.query(statement, [number]);
// If there is a customer with that phone number
// we return true, false otherwise.
return results.length;
}
insert(name, number) {
const statement = 'INSERT INTO customer (name, phone_number, points, is_activated) VALUES (?,?,?,?)';
return this.query(statement, [name, number, 0, true]);
}
query(query, placeholders) {
// We wrap the query in a promise
// So we can take advantage of async/await in the other functions
// To make the code easier to read avoiding callback hell
return new Promise((resolve, reject) => {
this.mysql.pool.query(query, placeholders, (error, results) => {
if(error)
return reject(error);
resolve(results);
});
});
}
}
module.exports = Customer;
<强>路由器强>
const Customer = require('./customer');
// ... rest of your code
router.post('/', async(req, res) => {
const customer = new Customer(req.app.get('mysql'));
try {
// We check whether the client exists or not
const check = await customer.check(req.body.phone_number);
if(!check) // We insert the customer if it doesn't exists
await customer.insert(req.body.name, req.body.phone_number);
// After successful insert or if the customer already exists
// we redirect to /view_customers
res.redirect('/view_customers');
} catch(error) {
// Probably a database error
console.log('Oops');
res.write(JSON.stringify(error));
res.end();
}
});
答案 1 :(得分:0)
你可以为它编写一个函数来返回一个简化事物的承诺,例如:
function checkFn(mysql, v) {
return new Promise((resolve, reject) => {
var customerCheck = "SELECT phone_number FROM customer WHERE phone_number=?";
var phoneNumberCheck = [v];
mysql.pool.query(customerCheck, phoneNumberCheck, function(error, results, fields){
if(error){
console.log("Failed to verify!");
reject(); // reject promise
}else{
console.log(results);
if(results.length){
console.log("phone number exists, not adding.");
resolve(true); // resolve promise with true
}else{
resolve(false); // resolve promise with false
}
}
})
})
}
然后您可以将它与async / await
一起使用router.post('/', async function(req, res){ // notice: async
try {
let numberExist = await checkFn(req.app.get('mysql'), req.body.phone_number)
if (numberExist) {
// do something if number exists
} else {
// do something if number doesn't exist
}
}
catch (e) {
// do something if error
}