在 js 中承诺库的最佳方法是什么?
What is the best way to promisify library in js?
在我之前的一篇文章中,我意识到我需要承诺(将回调转换为新的承诺)一个 npm 模块来进行干净的错误处理。问题是,我越是开始考虑组织 promisifing 图书馆,我就越是意识到它很容易变成一团糟。我应该如何在什么对象中访问 promisified 函数?我可以用新的 promisified 函数替换原来的库函数吗?我应该为承诺的功能创建一个新对象吗?示例:
const mongodb = require("mongodb");
const { MongoClient } = mongodb;
//Promisifing MongoClient.connect(), and storing it into connectPr into the original library
mongodb.MongoClient.connectPr = function (url) {
const options = { useNewUrlParser: true, useUnifiedTopology: true };
const promise = new Promise(function (resolve, reject) {
MongoClient.connect(url, options, (error, client) => {
if (error) reject(error);
else resolve(client);
});
});
return promise;
};
//Exporting whole module with added functions
module.exports = mongodb;
我在这里所做的只是修改原始库并添加新函数connectPr
。然后我导出它并在另一个文件中像这样使用它:
const mongodb = require("./helperMongoDB");
const { MongoClient } = mongodb;
const connectionURL = "mongodb://127.0.0.1:27017";
const databaseName = "tasker";
//Using new connectPr function
(async function () {
const client = await MongoClient.connectPr(connectionURL);
const db = client.db(databaseName);
db.collection("tasks").insertOne(
{
description: "Clean the house",
completed: true,
},
(error, result) => {
if (error) {
console.error(error);
return;
}
console.log(result.ops);
}
);
})();
如您所见,我仍然可以使用模块中的所有原始属性,也可以使用我的 connectPr 函数。这行得通,但没什么好看的。我敢肯定,如果我在一个团队中工作,他们中的大多数人会对为什么我通常不需要库以及为什么它隐藏在帮助文件中的某个地方感到困惑。做这种事的标准是什么?承诺回调函数是一种实践吗?
请务必首先检查异步 API 是否尚未提供 promise 接口。在您的问题中,您举了 mongodb 的例子。当未提供回调参数时,此节点 API 的异步方法将 return 一个承诺。
比如采用connect的方法。文档说:
Returns:
Promise if no callback passed
所以在 async
函数体中你可以这样写:
const client = await MongoClient.connect(url, options);
对于 Mongoose 库(建立在 Node MongoDb 驱动程序 API 之上),当使用 query 方法时,您可能需要链接一个 .exec()
调用,如 .
的答案中所述
任何想要保持正轨的异步库都将包含一个承诺 API。如果真的不是这种情况,请查看 Node 的 util.promisify
在我之前的一篇文章中,我意识到我需要承诺(将回调转换为新的承诺)一个 npm 模块来进行干净的错误处理。问题是,我越是开始考虑组织 promisifing 图书馆,我就越是意识到它很容易变成一团糟。我应该如何在什么对象中访问 promisified 函数?我可以用新的 promisified 函数替换原来的库函数吗?我应该为承诺的功能创建一个新对象吗?示例:
const mongodb = require("mongodb");
const { MongoClient } = mongodb;
//Promisifing MongoClient.connect(), and storing it into connectPr into the original library
mongodb.MongoClient.connectPr = function (url) {
const options = { useNewUrlParser: true, useUnifiedTopology: true };
const promise = new Promise(function (resolve, reject) {
MongoClient.connect(url, options, (error, client) => {
if (error) reject(error);
else resolve(client);
});
});
return promise;
};
//Exporting whole module with added functions
module.exports = mongodb;
我在这里所做的只是修改原始库并添加新函数connectPr
。然后我导出它并在另一个文件中像这样使用它:
const mongodb = require("./helperMongoDB");
const { MongoClient } = mongodb;
const connectionURL = "mongodb://127.0.0.1:27017";
const databaseName = "tasker";
//Using new connectPr function
(async function () {
const client = await MongoClient.connectPr(connectionURL);
const db = client.db(databaseName);
db.collection("tasks").insertOne(
{
description: "Clean the house",
completed: true,
},
(error, result) => {
if (error) {
console.error(error);
return;
}
console.log(result.ops);
}
);
})();
如您所见,我仍然可以使用模块中的所有原始属性,也可以使用我的 connectPr 函数。这行得通,但没什么好看的。我敢肯定,如果我在一个团队中工作,他们中的大多数人会对为什么我通常不需要库以及为什么它隐藏在帮助文件中的某个地方感到困惑。做这种事的标准是什么?承诺回调函数是一种实践吗?
请务必首先检查异步 API 是否尚未提供 promise 接口。在您的问题中,您举了 mongodb 的例子。当未提供回调参数时,此节点 API 的异步方法将 return 一个承诺。
比如采用connect的方法。文档说:
Returns:
Promise if no callback passed
所以在 async
函数体中你可以这样写:
const client = await MongoClient.connect(url, options);
对于 Mongoose 库(建立在 Node MongoDb 驱动程序 API 之上),当使用 query 方法时,您可能需要链接一个 .exec()
调用,如
任何想要保持正轨的异步库都将包含一个承诺 API。如果真的不是这种情况,请查看 Node 的 util.promisify