我正在构建一个小型node.js网站,其中包含一个用户界面,其中包含一个包含国家/地区列表的下拉列表。
以前,国家列表是用json文件硬编码的,我会读到:
exports.countries = require('./json/countries.json');
然后我意识到当我可以从mongodb数据库对列表进行distinct
查询时,我不应该像这样硬编码。
db.collection.distinct('c', {}, function(err, data) {
// something
});
但接下来是如何在该回调函数中提取data
变量的值的问题。我发现这有效:
db.collection.distinct('c', {}, function(err, data) {
if (err) {
throw Error('mongodb problem - unable to load distinct values');
} else {
exports.countries = data;
}
});
我是node.js的新手,这对我来说似乎很可疑。这是好的代码吗?使用发电机或承诺更好吗?如果我想使用发电机或承诺来做这件事,我该怎么做?
使用它的最终结果是在模板中。 ref.countries
是使用我的fishy代码的国家/地区的实际列表。如果我有承诺而不是国家列表,我将如何更改此代码?
<% ref.countries.forEach(function(c) { -%>
<option value="<%= c %>">
<%= ref.isoCodes[c] -%>
</option>
<% }); -%>
我使用的是节点v6.10.3。
答案 0 :(得分:0)
你说的出口&#34;工作&#34;是不可能使用的,因为加载模块的代码不知道何时实际设置了exports.countries
值,因为它是在异步调用中设置的,将在未来完成某些不确定的时间。此外,您无法处理该函数中的任何错误。
这样做的现代方法是导出一个函数,该函数在被调用时返回一个解析为数据的promise(或带有错误的拒绝)。加载模块的代码,然后调用导出的函数,获取promise,在promise上使用.then()
并使用.then()
处理程序中的数据。这可能看起来像这样:
function getCountries() {
return new Promise(function(resolve, reject) {
db.collection.distinct('c', {}, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
}
}
module.exports.getCountries = getCountries;
然后调用者会这样做:
const myModule = require('myModule');
myModule.getCountries().then(function(countries) {
console.log(countries);
// use country data here
}).catch(function(err) {
// deal with error here
});
目前,node.js的大多数数据库都内置了一定程度的承诺支持,因此您不必像上面所示那样围绕数据库函数创建自己的承诺包装,而是可以直接使用promise。从数据库引擎返回。它的工作原理特定于您使用的特定数据库/版本。
如果您在模板渲染操作中使用国家/地区列表,则必须获取国家/地区列表(以及模板渲染所需的任何其他数据),并且仅在所有数据时调用res.render()
已成功检索。这可能还会导致在检索到必要数据时出错时应该执行的操作。在这种情况下,您通常会回复页面请求的5xx错误代码,并且可能希望呈现某种错误页面,以便通知最终用户错误。
答案 1 :(得分:0)
我正在使用Node 6.10,所以我没有异步并等待,但如果我这样做,他们会帮助我:
https://developers.google.com/web/fundamentals/getting-started/primers/async-functions
相反,我可以使用asyncawait
库:
https://github.com/yortus/asyncawait
代码如下所示:
var async = require('asyncawait/async');
var await = require('asyncawait/await');
const db = require('_/db');
function getDistinctValues(key) {
return new Promise((resolve, reject) => {
db.collection.distinct(key, {}, function(err, data) {
if (err) {
throw Error('mongodb problem - unable to load distinct values');
} else {
resolve(data);
}
});
});
};
async(function () {
exports.countries = await(getDistinctValues('c'));
exports.categories = await(getDistinctValues('w'));
})();
现在我可以确保ref.countries
和ref.categories
在加载后可用。