2017-07-12 73 views
1

我知道sqlite(而不是sqlite3)模塊批量處理請求。我需要從數據庫中獲取一個值,賦值,然後對其進行一些處理。但是,在所有處理髮生之前,從數據庫獲取值的函數不會返回。NodeJS在繼續之前等待從sql.get分配變量

我需要三樣東西之一發生:

  1. 該函數立即返回
  2. 暫停代碼,直到myEvent.id已分配
  3. 製作sql.get立即返回

    myEvent.id = generateEventID(); 
    ///do stuff with myEvent.id 
    
    function generateEventID() { 
    return sql.get('SELECT * FROM settings WHERE name = "eventID"').then(row => { 
        if (!row) return message.reply("a database error occured while generating an ID"); 
        currentID = row.intValue + 1; 
        console.log("New eventID created: " + currentID); 
        sql.run(`UPDATE settings SET intValue = ${row.intValue + 1} WHERE name = "eventID"`); 
        return currentID; 
        }); 
    } 
    
+0

(https://github.com/mapbox/node-sqlite3)? node-sqlite3不支持promise。 –

+0

我做了RTFM,你很困惑node-sqlite https://github.com/kriasoft/node-sqlite 這是一個包裝的s​​qlite,promised使用回調。這在使用承諾的語言中很有用。 使用node-sqlite3 https://github.com/mapbox/node-sqlite3/ 該包裝承認具有極差的命名。 – Astrydax

回答

0

可惜你不能返回因爲sql.get(...)是異步的,所以直接離開函數10。

一種可能的方法來解決,這將是一個callback函數作爲參數傳遞給generateEventID()然後使主叫方等待callback功能的進一步進展之前被調用。

因此,你會看起來像這樣。

var doStuffWithEventId = function(eventId) { 
    // Do more stuff. 
} 

generateEventID(doStuffWithEventId); 


function generateEventID(callback) { 
    return sql.get('SELECT * FROM settings WHERE name = "eventID"').then(row => { 
     if (!row) return message.reply("a database error occured while generating an ID"); 
     currentID = row.intValue + 1; 
     console.log("New eventID created: " + currentID); 
     sql.run(`UPDATE settings SET intValue = ${row.intValue + 1} WHERE name = "eventID"`); 
     return callback(currentID); // Call function doStuffWithEventId with value of currentID variable 
    }); 
} 

這是完成你想要做的事情的一種方式。

這裏請注意。

  1. 您通常會在返回任何內容之前等待update操作。
  2. 您預計Id始終是1的增量。數據庫並不總是這樣做。所以你可能會陷入警惕。
  3. 您的代碼假定數據庫操作將始終成功。您通常會想要處理在進行外部呼叫時可能引發的潛在異常。
0

正如你已經說了,你的代碼應該在特定的順序提供三個主要功能:

  1. 從您的數據存儲(在這種情況下,SQL數據庫)獲取的結果。
  2. 在所獲得的數據(在sniippet稱爲 //do more stuff)執行特定操作
  3. 在你的數據存儲執行UPDATE查詢。

因此,您提供的實現邏輯是錯誤的,因爲它無法按特定順序執行三個操作。不要忘記,默認情況下,所有節點調用都是異步,在這種情況下,您無法強制執行所需的同步。要解決這個問題,您應該執行以下步驟:

  1. 從您的數據存儲中獲取結果。(已經完成了)。
  2. 對獲取的數據執行特定操作。這必須在sql.get()回調中完成,或者一旦承諾已經解決(因爲您在這種情況下使用承諾)。
  3. 對數據執行操作的方法(即步驟2)應返回新的承諾。一旦這個承諾得到解決,您將能夠致電您的UPDATE操作,並以這種方式確保您的實施將滿足您的所有要求。

現在,這是我會怎麼做:

generateEventID(); 

function doMoreStuff(eventId){ 
    return new Promise(function(resolve, reject){ 
    //do your stuff 
    if(err){ 
     reject(err) 
    }else{ 
     resolve() 
    } 
    }) 
} 

function generateEventID() { 
    return sql.get('SELECT * FROM settings WHERE name = "eventID"').then(row => { 
    if (!row) return message.reply("a database error occured while generating an ID"); 
    currentID = row.intValue + 1; 
    console.log("New eventID created: " + currentID); 
    doMoreStuff(currentID).then(function(){ //At this point your operations with currentId will have finished already 
     sql.run(`UPDATE settings SET intValue = ${row.intValue + 1} WHERE name = "eventID"`); 
    }); 
    }); 
} 

我真的希望這有助於!

編輯:別忘了你爲什麼不讀[手冊]執行錯誤處理的承諾與.catch()

+0

我不確定你指的是「節點調用」。我懷疑你正在嘗試說「函數調用」。如果這是真的,那麼這是不正確的。並非每個函數調用都是「異步」。如果每個函數調用都返回一個promise,那麼您會發現由於不必要的上下文切換,應用程序的運行速度會比平常慢很多。 –

+0

我的意思是節點I/O調用,因爲在這種情況下,我們正在處理SQL查詢。對不起,我忘了提及那些,但這些I/O調用是由異步方式由服務線程處理的。 –