2012-03-17 134 views
3

我在node.js.中寫了一個api。第一個Web服務端點 - /create - 創建一個帶有隨機6字符散列的新數據庫條目,就像bit.ly散列一樣。重構非阻塞nodejs do..while循環

在PHP中做了類似的事情之後,我編寫了一個do..while循環,它會生成一個隨機字符串並檢查我的mysql數據庫(使用node-mysql)以確保它是免費的。我還有一個計數器,所以如果需要的話,我可以在x迭代後失敗。

var i = 0; 
var alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; 
var hash = null; 
var success = false; 

do { 

    // generate a random hash by shuffling the alphabet, 
    // joining it and getting 6 chars 
    hash = alphabet.sort(function(){ 
     return 0.5 - Math.random(); 
    }).join('').substr(0,6); 

    console.log(i + ': checking hash ' + hash); 

    // see if it exists in the db 
    db.query("SELECT hash FROM trips WHERE hash = " + hash, function(err, results){ 

     if(results.length == 0) { 
      // the hash is free to use :) 
      success = true; 
     } else { 
      // the hash is already taken :(
      success = false; 
     } 

    }); 

    // increment the counter 
    i++; 

} while(success === false && i < 10); 

我目前只在我的分貝(abcdef)一個哈希值,但環越來越十和失敗,因爲它認爲每一個新的哈希值已經存在。

我敢肯定,這是因爲node.js的非阻塞性質。這顯然是一件好事,但在我的情況下,我需要循環來阻止,直到查詢返回。

我敢肯定,我可以做這樣的事情破解這樣的:

var q = db.query(...); 

但我知道這是扔掉node.js中的一大特色

是否有這種需求的代碼模式?

+0

請注意,我做了一個小的變化,以我的答案。 – Tomalak 2012-03-17 21:54:48

回答

3

我敢肯定,這是因爲node.js的非阻塞性質。

是的。

這顯然是一件好事,但在我的情況下,我需要循環阻塞,直到查詢返回。

不,你肯定不想這樣做。

擁抱異步接近。有回調的工作:

function generateHash(onSuccess, onError, retryCount) { 
    // generate a random hash by shuffling the alphabet, 
    // joining it and getting 6 chars 
    var hash = alphabet.sort(function(){ 
     return 0.5 - Math.random(); 
    }).join('').substr(0,6); 

    // see if it exists in the db 
    db.query(
    "SELECT hash FROM trips WHERE hash = '" + hash + "'", 
    function(err, results){ 
     if (results.length == 0) { 
      // the hash is free to use :) 
      onSuccess(hash); 
     } else { 
      // the hash is already taken :(
      if (retryCount > 1) { 
       generateHash(onSuccess, onError, retryCount - 1); 
      } else { 
       onError(); 
       } 
      } 
     } 
    }); 
} 

generateHash(
    function(hash) { console.log('Success! New hash created: ' + hash); }, 
    function() { console.log('Error! retry limit reached'); }, 
    6 
); 
+0

爲什麼setTimeout? – 2012-03-17 20:57:04

+0

@Andrey避免遞歸。 – Tomalak 2012-03-17 20:59:22

+0

你已經在回調處理程序中,沒有遞歸,調用通過事件循環路由 – 2012-03-17 21:01:24

2
var i=0; 

function generateHash(callback) { 
    // generate a random hash by shuffling the alphabet, 
    // joining it and getting 6 chars 
    hash = alphabet.sort(function(){ 
     return 0.5 - Math.random(); 
    }).join('').substr(0,6); 

    console.log(i + ': checking hash ' + hash); 

    // see if it exists in the db 
    db.query("SELECT hash FROM trips WHERE hash = " + hash, function(err, results){ 

     if(results.length == 0) { 
      // the hash is free to use :) 
      callback(null, hash); 
     } else { 
      // increment the counter 
      i++; 
      if (i < 10) 
       generateHash(callback); //another attempt 
      else 
       callback('error'); // return result 

     } 
    }); 
} 
+0

+1(我認爲在參數中傳輸重試計數比爲它創建一個外部作用域變量更清潔),但是 – Tomalak 2012-03-17 21:56:18

+0

同意,param與外部作用域變量更好 – 2012-03-18 13:38:02