Node.js中使用JavaScript回调实现邮箱和手机号唯一性注册校验
Got it, let's work through how to implement unique email and phone validation for registration using callbacks in Node.js. I'll build this out with your existing code structure in mind, making sure it's practical and follows Node.js best practices.
Complete Implementation
First, let's assume you already have a database connection set up (using a library like mysql or mysql2). Here's the full code that ties together validation, database queries, and registration logic:
// Import your existing database connection const db = require('./path-to-your-db-connection'); // Registration function with callback-based validation function registerUser(userData, callback) { // Extract the fields we need from the user input const { email, phone, username, password } = userData; // Step 1: Check if email already exists in the database const checkEmailQuery = 'SELECT id FROM users WHERE email = ?'; db.query(checkEmailQuery, [email], (err, emailResults) => { // Handle database errors first if (err) { return callback(err); } // If email exists, return a business error if (emailResults.length > 0) { return callback(new Error('该邮箱已被注册')); } // Step 2: Check if phone number already exists const checkPhoneQuery = 'SELECT id FROM users WHERE phone = ?'; db.query(checkPhoneQuery, [phone], (err, phoneResults) => { if (err) { return callback(err); } if (phoneResults.length > 0) { return callback(new Error('该手机号已被注册')); } // Step 3: Both validations passed, proceed to register the user // IMPORTANT: Always hash passwords before storing them! // Uncomment below if using bcrypt (install via npm i bcrypt) // const hashedPassword = bcrypt.hashSync(password, 10); const insertUserQuery = 'INSERT INTO users (username, email, phone, password) VALUES (?, ?, ?, ?)'; db.query(insertUserQuery, [username, email, phone, password], (err, result) => { if (err) { return callback(err); } // Return success with the new user ID callback(null, { userId: result.insertId, message: '注册成功' }); }); }); }); } // Example usage const newUser = { username: 'john_doe', email: 'john@example.com', phone: '1234567890', password: 'MySecurePassword123!' }; registerUser(newUser, (err, result) => { if (err) { console.error('注册失败:', err.message); return; } console.log('成功:', result); });
Key Details & Best Practices
- 错误优先回调:这遵循Node.js标准的回调模式,第一个参数始终是错误(无错误则为
null),第二个是结果。这种模式让你的代码错误处理更一致。 - 参数化查询:用
?占位符编写SQL查询,能防止SQL注入攻击——这是必须的安全措施。 - 密码加密:我添加了关于使用
bcrypt加密密码的注释。绝对不要在数据库中存储明文密码,一定要用强算法加密后再存储。 - 串行校验的嵌套回调:我们先检查邮箱,再检查手机号,确认都通过后才执行用户插入操作,确保只有校验完全通过才会创建新用户。
优化版:并行校验(更快!)
如果想同时检查邮箱和手机号来节省时间(代替串行检查),可以用计数器来跟踪两个查询的完成状态:
function registerUserParallel(userData, callback) { const { email, phone, username, password } = userData; let completedChecks = 0; const validationErrors = []; // 并行检查邮箱 db.query('SELECT id FROM users WHERE email = ?', [email], (err, res) => { completedChecks++; if (err) validationErrors.push(err); else if (res.length > 0) validationErrors.push(new Error('邮箱已被注册')); finalizeCheck(); }); // 并行检查手机号 db.query('SELECT id FROM users WHERE phone = ?', [phone], (err, res) => { completedChecks++; if (err) validationErrors.push(err); else if (res.length > 0) validationErrors.push(new Error('手机号已被注册')); finalizeCheck(); }); // 两个检查都完成后执行 function finalizeCheck() { if (completedChecks !== 2) return; if (validationErrors.length > 0) { // 返回第一个遇到的错误 return callback(validationErrors[0]); } // 执行注册(别忘了加密密码!) db.query( 'INSERT INTO users (username, email, phone, password) VALUES (?, ?, ?, ?)', [username, email, phone, password], (err, result) => { if (err) return callback(err); callback(null, { userId: result.insertId, message: '注册成功' }); } ); } }
这种并行方式能减少总等待时间,因为两个数据库查询会同时执行,而不是依次执行。
额外提示
- 输入格式校验:在调用数据库之前,先添加邮箱/手机号格式检查(比如用正则表达式),避免不必要的数据库请求。
- 连接池:使用数据库连接池(多数SQL库都支持)来高效管理数据库连接,尤其是在高流量应用中。
- 错误信息:自定义用户友好的错误提示,但不要向用户暴露过多技术细节。
内容的提问来源于stack exchange,提问作者user6038209
相关产品推荐
相关产品推荐

