繁体   English   中英

数据库调用函数没有回调Node.js和Postgresql

[英]Database call in a function without callback with Node.js and Postgresql

我正在我的一个项目上尝试框架node.js。 我真的看到了他们所谓的“事件驱动,非阻塞I / O模型”的一些优势,但是如果我的项目有一些时刻我不一定想要一些异步调用并且能够启动一些异步调用之前的几个操作。

特别是当我想做一些分解并创建一些功能时。

通常我有以下情况:我知道在我的程序的几个部分中,我必须检查我的数据库中是否存在用于给定字符串或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的核心概念,也许我的方法是错误的,我提前道歉。 我知道在做某事之前等待回应并不好。 但是替代方案是什么? 当我需要在代码的几个部分中使用某些功能时,如何将代码分解为函数?

因此,如果有人能够通过编程的最佳实践来解释如何做到这一点,那就太棒了。

谢谢

安塞尔姆

正如科迪所说,你可能不想做同步功能。

你应该如何处理你的例子中的情况就是传递你自己的回调

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 {

    }
});

如果你最终得到一堆硬回调,承诺真的值得研究。

我不认为你真的想要一个同步调用。 节点中同步调用的问题在于它会在同步函数运行时停止整个进程执行任何操作 ,因为它将停止事件循环。 举个例子,假设您的同步功能需要2秒钟才能完成。 然后,您的服务器将在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)
  })
}

随着新的ES6加上异步的东西和babel它更简单。 你可以npm i -g babel npm i babel-runtime然后使用babel test.js --optional runtime --stage 2 | node编译并运行以下babel test.js --optional runtime --stage 2 | node 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)});            

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM