簡體   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