2012-03-17 119 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