javascript - 使用异步函数调用创建新的承诺是不好的做法吗?
问题描述
片段来自 node.js 和 mongoDB CRUD 应用程序。Github repo 获取完整代码。代码工作正常,但不确定我的结构和使用 promises 和 async await 是否是不好的做法。
handlers._newbies = {};
handlers._newbies.post = (parsedReq, res) => {
const newbie = JSON.parse(parsedReq.payload);
databaseCalls.create(newbie)
.then((result) => {
res.writeHead(200,{'Content-Type' : 'application/json'});
const resultToString = JSON.stringify(result.ops[0]);
res.write(resultToString);
res.end();
})
.catch(err => console.log(err));
};
const databaseCalls = {};
databaseCalls.create = (newbie) => {
return new Promise(async (resolve, reject) => {
try {
const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
console.log("Connected correctly to server");
const db = client.db('Noob-List');
const result = await db.collection('newbies').insertOne(newbie);
client.close();
resolve(result);
} catch(err) {
console.log(err);
}
});
};
当节点服务器收到带有 JSON 有效负载的 POST 请求时,它会调用 handlers._newbies.post 处理程序,该处理程序获取有效负载并将其传递给
const newbie = JSON.parse(parsedReq.payload);
databaseCalls.create(newbie)
称呼。我希望这个数据库调用返回一个保存db.collection('newbies').insertOne(newbie);
调用结果的承诺。我在返回 insertOne 返回的承诺时遇到了麻烦,因为返回后我无法调用client.close();
。
同样,也许我在这里所做的一切都很好,但我还没有在网上找到任何关于创建带有承诺的承诺。感谢您抽出宝贵时间让我知道我的问题不清楚的地方。
解决方案
将现有的 Promise 包装在手动创建的 Promise 中被认为是一种反模式,因为没有理由这样做,而且它会产生许多错误机会,尤其是在错误处理方面。
而且,就您而言,您有几个错误处理问题。
- 如果您在数据库代码的任何地方出现错误,您将永远不会解决或拒绝您正在创建的承诺。这是反模式的一个经典问题。
- 如果打开数据库后出现错误,请不要关闭数据库
- 您不会向调用者反馈错误。
.create()
以下是在没有反模式且没有上述问题的情况下如何执行功能的方法:
databaseCalls.create = async function(newbie) {
let client;
try {
client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
console.log("Connected correctly to server");
const db = client.db('Noob-List');
return db.collection('newbies').insertOne(newbie);
} catch(err) {
// log error, but still reject the promise
console.log(err);
throw err;
} finally {
// clean up any open database
if (client) {
client.close();
}
}
}
然后,你会这样使用:
databaseCalls.create(something).then(result => {
console.log("succeeded");'
}).catch(err => {
console.log(err);
});
仅供参考,我还修改了其他一些东西:
- 数据库连接已关闭,即使在错误情况下也是如此
- 该函数返回一个由以下结果解决的承诺
.insertOne()
(如果那里有有意义的结果) - 如果有错误,返回的 Promise 会因该错误而被拒绝
与您的承诺问题并不特别相关,但您通常不希望在每次操作时打开和关闭数据库连接。您可以使用一个持久连接,也可以创建一个连接池,您可以从池中获取一个连接,然后在完成后将其放回池中(大多数数据库具有用于服务器端工作的这种类型的功能)。
推荐阅读
- python - 从 python 中 pywin32 的方法 dispatch(Excel.Application) 获取“com_error: (-2147221005, 'Invalid class string', None, None)”
- python - Python - Pandas - .str.contains 过滤多个列
- kubernetes - 如何在 Helm 中使用 if/else 循环
- java - 谁能帮我解决这个错误?它在 Android Studio 上显示“IDE 内部错误”
- reactjs - 如何解决反应中的以下错误 - 'Firebase: No Firebase App '[DEFAULT]' has been created'?
- asp.net - 负载均衡器背后的 Asp.net GenericJsonWebHook
- c - 如何在 Linux 或 Windows 中执行 C 程序打印文件的简单命令
- angular - 如何修复 package.json angular 10 中的依赖项 ERROR 404?
- flutter - 无法在本地加载iap产品,它永远等待
- elasticsearch - 使用邮递员进行 Elasticsearch - 找不到 uri 的处理程序