我在我的一个项目上尝试了框架node.js。 我真的看到了他们所谓的“事件驱动,非阻塞I / O模型”和“#34;但是如果我的项目有一些时刻我不一定想要进行一些异步调用,并且能够在启动一些异步调用之前进行多次操作。
特别是当我想做一些分解并创建一些功能时。
通常我有以下情况: 我知道在我的程序的几个部分中,我必须检查我的数据库中是否存在针对给定字符串或id的媒体。
因此,作为一个试图保持整理的人,我想创建一个我每次需要检查时都会调用的函数。 但是,我没有找到使用node.js和pg(npm PostgreSQL库(https://github.com/brianc/node-postgres/)的方法。事实上,函数中始终存在回调,并且由于回调,返回值为null。以下是一个示例
/*
Function which is supposed to check if a media existing
*/
function is_media_existing (url_or_id){
log.debug("is_media_existing : begin of the function", {"Parameter" : url_or_id});
pg.connect(connectionstring, function (err, client, done) {
if (err) {
log.warning("is_media_existing : Problem with Database connection", {
"Parameter": url_or_id,
"Error": err
});
}
if (isNaN(url_or_id)) {
// Case is parameter is not a number (string)
var query = client.query('SELECT COUNT(*) as count FROM media WHERE url = $1::string ', url_or_id);
query.on('error', function (error) {
log.warning("is_media_existing : Problem with Database query (connection to db passed but not query " +
"", {"Parameter": url_or_id, "Error": error});
});
return query;
} else {
// Case is parameter is a int
log.debug("is_media_existing : Type of Parameter is a string");
// Case is parameter is not a number (string)
var query = client.query('SELECT COUNT(*) as count FROM media WHERE id = $1::id ', url_or_id);
query.on('error', function (error) {
log.warning("is_media_existing : Problem with Database query (connection to db passed but not query " +
"", {"Parameter": url_or_id, "Error": error});
});
return query;
}
});
}
// Executing the function
var test = is_media_existing("http://random_url_existing_in_db");
// test is always null as the return is in a callback and the callback is asynchronous
我觉得我的问题是触及node.js的核心概念,也许我的方法是错误的,我提前道歉。 我知道在做某事之前等待回应并不好。 但是替代方案是什么?当我需要在代码的几个部分中使用某些功能时,如何将代码分解为函数?
因此,如果有人能够通过最佳编程实践解释如何做到这一点,那就太棒了。
由于
安塞尔姆
答案 0 :(得分:4)
正如Cody所说,你可能不想做同步功能。
你应该如何处理你的例子中的情况就是像这样传递你自己的回调
function is_media_existing (url_or_id, callback){
然后代替return query;
使用你的回调 -
callback(query);
或者可能更好地遵循回调函数的节点约定,有两个参数(err, result)
,所以你的回调看起来像这样
callback(null, query);
以下是您的样本的返工
function is_media_existing (url_or_id, callback){ /* callback(err, result) */
log.debug("is_media_existing : begin of the function", {"Parameter" : url_or_id});
pg.connect(connectionstring, function (err, client, done) {
if (err) {
done(err);
log.warning("is_media_existing : Problem with Database connection", {
"Parameter": url_or_id,
"Error": err
});
return callback(err, null);
/* note that this return is simply used to exit the connect's callback and the return value is typically
* not used it is the call to callback() that returns the error value */
}
var qrystr;
if (isNaN(url_or_id)) {
log.debug("is_media_existing : Type of Parameter is a string");
qrystr = 'SELECT COUNT(*) as count FROM media WHERE url = $1::string;';
} else {
qrystr = 'SELECT COUNT(*) as count FROM media WHERE id = $1::id;';
}
client.query(qrystr, [url_or_id], function(err, result){
done();
if(err){
/* .. */
}
callback(err, result);
});
});
}
// Executing the function
var test = is_media_existing("http://random_url_existing_in_db", function(err, result){
if(err){
}else {
}
});
如果你最终得到一堆硬回调,那么承诺真的值得研究。
答案 1 :(得分:1)
我不认为你真的做想要同步通话。节点中同步调用的问题在于它会在同步函数运行时停止整个进程执行任何,因为它将停止事件循环。举个例子,假设您的同步功能需要2秒钟才能完成。然后,您的服务器将执行 nothing 2整秒。 2秒包括所有(接受新连接,其他所有内容等)。阻止功能不存在的原因是因为它们(非常)不好。以下是您的函数将如何在异步庄园中做出反应的示例。
is_media_existing("http://random_url_existing_in_db", function(exists){
if (exists){
//do stuff
} else {
//do this other stuff
}
});
然后在is_media_existing
内,您需要在查询完成时调用该回调函数。
//psuedo
function is_media_existing(url, callback){
query('select COUNT(*) as count FROM media WHERE id = $1::id '. [url], function(err, result){
if (err)
callback(false)
else
callback(result.count > 0)
})
}
答案 2 :(得分:0)
使用新的ES6加异步功能和babel更简单。您可以npm i -g babel
npm i babel-runtime
然后使用babel test.js --optional runtime --stage 2 | node
编译并运行以下内容。请仔细阅读以下示例,了解如何使其适应您的使用案例:
let testData = [
{ id: 0, childIds: [1,2]},
{ id: 1, childIds:[] }
];
function dbGet(ids) {
return new Promise( r=> {
// this an example; you could do any db
// query here and call r with the results
r(ids.map((id) => { return testData[id];}));
});
}
async function dbExists(ids) {
let found = await dbGet(ids);
return (found && found.length>0);
}
async function test() {
var exists = await dbExists([0]);
console.log(exists);
}
test().then(f=>{}).catch( e=> {console.log('e',e)});