2015-10-09 2 views
1

Что я хочу сделать:Node.js обратного вызова в то время как

var found = false; 
while (!found){ 
    var result = db.getNextRecord(); 
    if (result == search_term){ 
    return result; 
    } 
} 

Проблема заключается в том, getNextRecord асинхронный

var nothing_returned = db.getNextRecord(function(err, result){ 
    // I have the result in this callback, but not before 
}); 

Учитывая поведение getNextRecord (Cb), как я могу переписать над фрагментом кода, чтобы получить тот же результат?

+0

FYI это идеальный случай использования для генераторов, где вы могли бы сделать "выход db.getNextRecord();" и цикл остановится до тех пор, пока асинхронный вызов не будет разрешен. Генераторы приходят в javascript в ECMA 7 (вы можете использовать их сейчас с транспилером, как babel) и уже поддерживаются в node.js –

ответ

1

Поскольку у вас есть функция async, и вы хотите звонить синхронно, у вас есть два варианта. Используйте версию метода sync, если есть один доступный, но если нет, то вам придется изменить свою логику.

Следующий фрагмент должен делать то, что вы хотите, он требует библиотеки async.

var async = require('async'); 
var result; 

async.whilst(
    function() { 
     return !result; 
    }, 
    function (callback) { 
     db.getNextRecord(function (err, record) { 
      if (err) 
      { 
       return callback(err); 
      } 

      if (result == search_term) 
      { 
       result = record; 
      } 

      return callback(); 
     }); 
    }, 
    function (err) { 

     // Search is complete, do what you wish with result in this function. This function 
     // will be called when whilst is done or if getNextRecord got an error. 

    } 
); 

Я уверен, что есть более короткий путь, чтобы сделать это, если вы хотите, чтобы изменить логику еще больше, но это похоже на делать while но асинхронно.

+0

Я немного смущен, так как вы используете запись и результат. Где результат определяется, когда он впервые используется в операторе if ближе к середине вашего кода? – Dave

1

Используйте библиотеку async. Его until функция выглядит то, что вам нужно: https://www.npmjs.com/package/async#until

var async = require('async'); 

var latestResult = null; 

async.until(function() { 
    return latestResult == search_term; 
}, function() { 
    db.getNextRecord(function (err, result) { 
    latestResult = result; 
    }); 
}, function() { 
    // now you can do something with latestResult 
}); 

Вы должны также рассмотреть вопрос, имеет ли смысл делать это в вашем приложении или есть запрос к базе данных включает в себя эту фильтрацию.

+0

Какие переменные имеет доступ к тестовой функции? Я предполагаю, что search_term определен выше, но можно ли предположить, что все, что установлено в обратном вызове getNextRecord, доступно для тестирования? – Dave

+0

Вот что я пытался выяснить раньше. Было бы неплохо, если getNextRecord мог передать переменную тестовой функции, но я не видел никакого способа сделать это, таким образом, закрытие во внешней области. – Brandon

0

С babel и новые JS:

import {promisify as pr} from 'es6-promisify'; 

async function find(search_term) { 
    let found = false, result=null; 
    while (!found){ 
    let result = await pr(db.getNextRecord)(); 
    if (result == search_term){ 
     found=true; 
    } 
    } 
    return result; 
} 
+0

Как ждать, чтобы узнать, что результатом является второй параметр getNextRecord, а не первый? – Dave

+0

Promisify преобразует стандартный обратный вызов Node с ошибкой сначала на обещание, а async/await работает с обещаниями. Исследование «es7 async» javascript обещает «babel». Для изучения этого материала потребуется некоторое время и практика. –

Смежные вопросы