Рефакторинг неблокирующих узловых узлов do.. while - PullRequest
3 голосов
/ 18 марта 2012

Я пишу API в node.js. Первая конечная точка веб-сервиса - /create - создает новую запись в БД с рандомизированным 6-символьным хешем, очень похожим на хэш bit.ly.

Сделав нечто подобное в PHP, я написал цикл do..while, который генерирует случайную строку и проверяет мой mysql db (используя 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.

Существует ли шаблон кода для такого рода потребностей?

Ответы [ 2 ]

3 голосов
/ 18 марта 2012

Я почти уверен, что это из-за неблокирующей природы 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
);
2 голосов
/ 18 марта 2012
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

        }
    });
}
...