最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Database call in a function without callback with Node.js and Postgresql - Stack Overflow

programmeradmin1浏览0评论

I'm trying out the framework node.js on one of my projects. I'm really seeing some good advantages on what they called "event-driven, non-blocking I/O model" however if my project there are some moments where I don't necessarily want to have some asynchronous calls and to be able to several operation before launching some asynchronous call.

Especially when I want to do some factorization and create some functions.

Typically I have the following case: I know that in several part of my program I have to check if a media is existing in my database for a given string or id.

So as a guy who tried to stay organize I want to create a function that I will call each time I need to check this. However, I did not find the way to do that with node.js and pg (the npm PostgreSQL library (/) . Indeed, there is always a callback in the function and the return is null because of the callback. Here is an example below

/*
    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 

i have the feeling my question is touching the core concepts of node.js, and perhaps my approach is wrong and I apologize in advance. I know it's not good to wait for a response before doing something. But what's the alternative? How can I factorize my code into functions when I need some functionalities in several part of my code?

So if there would be anyone who could explain how to do that with a best practice of programming it would be great.

Thanks

Anselme

I'm trying out the framework node.js on one of my projects. I'm really seeing some good advantages on what they called "event-driven, non-blocking I/O model" however if my project there are some moments where I don't necessarily want to have some asynchronous calls and to be able to several operation before launching some asynchronous call.

Especially when I want to do some factorization and create some functions.

Typically I have the following case: I know that in several part of my program I have to check if a media is existing in my database for a given string or id.

So as a guy who tried to stay organize I want to create a function that I will call each time I need to check this. However, I did not find the way to do that with node.js and pg (the npm PostgreSQL library (https://github./brianc/node-postgres/) . Indeed, there is always a callback in the function and the return is null because of the callback. Here is an example below

/*
    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 

i have the feeling my question is touching the core concepts of node.js, and perhaps my approach is wrong and I apologize in advance. I know it's not good to wait for a response before doing something. But what's the alternative? How can I factorize my code into functions when I need some functionalities in several part of my code?

So if there would be anyone who could explain how to do that with a best practice of programming it would be great.

Thanks

Anselme

Share Improve this question edited Sep 16, 2015 at 15:56 Anselme asked Sep 14, 2015 at 19:19 AnselmeAnselme 5072 gold badges11 silver badges32 bronze badges 4
  • Does this StackOverflow question help? – dsh Commented Sep 14, 2015 at 20:23
  • Thanks dsh your proposal. However after viewing your link, I'm more looking for synchronous solution. Or what would be best the way to factorize such a functionality! – Anselme Commented Sep 15, 2015 at 16:05
  • 1 There is no synchronous solution unless you want to block your execution thread. This may interest you strongloop./strongblog/… – Luis Sieira Commented Sep 16, 2015 at 19:52
  • Use of promises is a good approach to your tasks. Check out pg-promise. – vitaly-t Commented Nov 11, 2015 at 0:55
Add a ment  | 

3 Answers 3

Reset to default 4 +50

As Cody says, you probably dont want to do synchronous function.

The way you should handle the situation in your example is to pass in your own callback like this

function is_media_existing (url_or_id, callback){

and then instead of return query; use your callback like this-

callback(query);

or probably better to follow the node convention for callback functions to have two parameters (err, result) so your callback would look like this

callback(null, query);

Here is a rework of your sample

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 {

    }
});

If you end up with a hard nest of callbacks, promises are really worth looking into.

I don't think you really do want a synchronous call. The problem with synchronous calls in node is that it stops the entire process from doing anything while a synchronous function is running as it will stop the event loop. As an example lets say your sync function takes 2 seconds to plete. Your server will then do nothing for 2 full seconds. That 2 seconds includes everything (accepting new connections, everything else, etc). The reason blocking functions don't exist is because they are (very) bad. Here is an example how your function will react in an async manor.

is_media_existing("http://random_url_existing_in_db", function(exists){
  if (exists){
    //do stuff
  } else {
    //do this other stuff
  }
});

Then within is_media_existing you will need to call that callback function when your query pletes.

//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)
  })
}

With the new ES6 plus async stuff and babel its simpler. You can npm i -g babel npm i babel-runtime then pile and run the following with babel test.js --optional runtime --stage 2 | node. Please read the following example carefully to see how to adapt it to your use case:

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)});            
发布评论

评论列表(0)

  1. 暂无评论