Async函数未执行后续代码求助:Mongoose连接状态检测异常
MongoDB连接异步等待问题修复
问题场景
我想构建一个async函数,确保后续步骤必须等待该函数执行完成后再启动。编写了连接MongoDB服务器及检测连接状态的模块,两个函数单独运行正常,但调用时await checkState()之后的console.log("Do this next")从未执行,怀疑是resolve的使用有问题。
原数据库配置模块代码
const mongoose = require('mongoose'); const mongoServer = `mongodb://127.0.0.1/my_database`; const consoleColor = { green: '\x1b[42m%s\x1b[0m', yellow: '\x1b[43m%s\x1b[0m', red: '\x1b[41m%s\x1b[0m' } exports.connectMongoose = () => { mongoose.connect(mongoServer, { useNewUrlParser: true }); } exports.checkState = () => { const mongooseState = mongoose.STATES[mongoose.connection.readyState]; return new Promise((resolve) => { if (mongooseState === 'connected') { console.log(consoleColor.green, `Mongoose is ${mongooseState}.`); resolve(); } else if (mongooseState === 'connecting') { console.log(`Mongoose is ${mongooseState}.`); setTimeout(() => { this.checkState(); }, 1000); } else { console.log(consoleColor.red, `Mongoose is ${mongooseState}.`); } }); }
调用代码
const dbconfig = require('./dbconfig') dbconfig.connectMongoose() const testAwait = async () => { await dbconfig.checkState(); console.log("Do this next"); } testAwait()
问题分析
checkState的Promise永远无法resolve(当状态为connecting时):当连接处于connecting状态时,通过setTimeout递归调用this.checkState(),但这里的this指向setTimeout的回调上下文,并非模块导出对象,递归调用的是不存在的方法;就算调用正确,递归产生的新Promise和外层返回的Promise没有关联,外层Promise永远不会被resolve,导致await一直挂起。connectMongoose未利用mongoose.connect的原生Promise:mongoose.connect本身返回Promise,无需手动轮询状态,直接利用原生Promise更可靠。
修复方案
方案一:修复原有checkState函数
修改checkState,确保递归时关联外层Promise,同时处理连接失败的reject场景:
const mongoose = require('mongoose'); const mongoServer = `mongodb://127.0.0.1/my_database`; const consoleColor = { green: '\x1b[42m%s\x1b[0m', yellow: '\x1b[43m%s\x1b[0m', red: '\x1b[41m%s\x1b[0m' } exports.connectMongoose = () => { mongoose.connect(mongoServer, { useNewUrlParser: true }); } exports.checkState = () => { return new Promise((resolve, reject) => { const check = () => { const mongooseState = mongoose.STATES[mongoose.connection.readyState]; if (mongooseState === 'connected') { console.log(consoleColor.green, `Mongoose is ${mongooseState}.`); resolve(); } else if (mongooseState === 'connecting') { console.log(`Mongoose is ${mongooseState}.`); setTimeout(check, 1000); } else { const errMsg = `Mongoose is ${mongooseState}.`; console.log(consoleColor.red, errMsg); reject(new Error(errMsg)); } }; check(); }); }
方案二:直接利用mongoose.connect的原生Promise(更简洁可靠)
无需手动轮询状态,直接使用mongoose.connect返回的Promise处理连接逻辑:
const mongoose = require('mongoose'); const mongoServer = `mongodb://127.0.0.1/my_database`; const consoleColor = { green: '\x1b[42m%s\x1b[0m', yellow: '\x1b[43m%s\x1b[0m', red: '\x1b[41m%s\x1b[0m' } // 让connectMongoose返回Promise exports.connectMongoose = () => { return mongoose.connect(mongoServer, { useNewUrlParser: true }) .then(() => { console.log(consoleColor.green, `Mongoose is connected.`); }) .catch(err => { console.log(consoleColor.red, `Mongoose connection failed: ${err.message}`); throw err; }); }
对应的调用代码修改为:
const dbconfig = require('./dbconfig') const testAwait = async () => { // 直接await连接Promise,连接成功后执行后续代码 await dbconfig.connectMongoose(); console.log("Do this next"); } // 捕获连接失败的错误 testAwait().catch(err => console.error(err));
说明
方案二更推荐,它利用mongoose原生异步处理机制,避免手动轮询可能带来的错误,代码简洁且可靠性更高。
内容的提问来源于stack exchange,提问作者Dynacel
相关产品推荐
相关产品推荐

