2013-10-08 2 views
2

Я нахожусь в точке теста, где мне нужен цикл вложенных циклов, но я теряюсь со всей стороной Async. В основном, что происходит сейчас, я хочу перебирать массив и использовать значения один за другим и записывать выходные данные. Что происходит в настоящее время, так это то, что единственный регистрируемый вывод - это последние значения, которые я хочу использовать. Трудно объяснить, поэтому я буду показывать свой код.Вложенные для циклов в Node.js вместе с тестовой средой Mocha

// For the sake of it, all these values are strings 
var arr1 = [ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 1, 2, 3] ]; 
var arr2 = [ [a, b, c, d], [b, c, d, a], [c, d, a, b], [d, a, b, c] ]; 

for(var i = 0; i < arr1.length; i++){ 
    describe("Test", function(){ 
     it("Does something", function(done){ 
      for(var x = 0; x < arr2.length; x++){ 
       it("Does something else", function(done){ 
        // Do stuff with arr1[i], arr2[x] etc. 
        testFunc(arr1[i], arr2[x], function(returnValue){ 
         assert.strictEqual(returnValue, true, "Passed!"); 
         done(); 
        } 
       }); 
      } 
     }); 
    }); 
} 

Теперь, я не в состоянии заполнить в том, что код на самом деле делает (причины конфиденциальности), но если кто-то может указывать мне так, как я могу сделать эту работу (имеется в виду ожидания петли на обратный вызов от testFunc() каждый раз).

Если мы говорим, что testFunc() выглядит следующим образом:

function testFunc(arr1var, arr2var, callback){ 
    console.log(arr1var + " and " + arr2var); 
} 

Когда я запускаю его, все, что я вижу, это конечные значения, передаваемые в консоли («3 и с»).

Я искал это для этого, но потому, что примеры людей настолько специфичны для их кода, что смущает попробовать и адаптироваться. Я посмотрел модуль Node.js Async, но также не получил слишком далеко.

Если кто-то может говорить мне через все это шаг за шагом или переписать выше, чтобы работать так, как я хочу, я был бы признателен.

Кроме того, в моем фактическом коде мои массивы имеют разные размеры в верхней части - в случае, если это вызывает разницу.

Поскольку несколько человек указали на это, я просто добавлю, что я полностью открыт для предложений, если у кого есть лучший метод. Я буду запускать ~ 40 тестов, и это сократит его до 10-15 строк кода, а не 200, называя каждого по отдельности, так что, как думают люди, лучше всего, не стесняйтесь советовать мне.

+0

Это похоже на реализацию O (n!). Вы уверены, что нет лучшего подхода? –

+0

@TravisJ В моем фактическом коде мне нужно проверить 'arr1 [0]' рядом со всеми элементами в 'arr2', затем' arr1 [1] 'вдоль всех элементов в' arr2' и т. Д. Всего должно быть 40 тестов (в моем фактическом коде, а не здесь). Я не уверен, есть ли лучший способ, вы думаете, что он будет? – whitfin

+1

Использование цикла для генерации тестов - это запах кода –

ответ

3

Я не вижу запаха кода в вашем примере. Вам просто нужно использовать async.each вместо ваших циклов. Кроме того, я не понимаю, почему вам нужны два его утверждения. Я бы вместо этого сделал что-то вроде:

var async = require('async'); 
var expect = require('expect.js'); 
var _ = require('lodash'); 
var arr1 = [ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 1, 2, 3] ]; 
var arr2 = [ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 2, 2, 3] ]; 

describe('Array tests', function() { 
    async.each(arr1, function(arr1Element, callback) { 
    async.each(arr2, function(arr2Element, callback2) { 
     it('Tests array elements', function(done) { 
     expect(_.difference(arr1Element, arr2Element)).to.be.empty(); 
     done(); 
     }); 
     callback2(); 
    }); 
    callback(); 
    }); 
}); 
+0

Мне нужны были два, потому что между ними было что-то среднее, но вы правы - я могу избавиться от него. Я попытался посмотреть на async.each, но немного потерял во всем этом. Спасибо за пример, и я дам вам знать, как это происходит, когда я пытаюсь! – whitfin

+0

Я забыл упомянуть, что я проверил код выше; оно работает. – dankohn

+0

Да, я адаптировал его к своему действительному коду, и он работает :) Раздражающе, у меня было почти то же самое, но я переименовал обратные вызовы, и это не сработало. – whitfin

2

Проблема в том, что первая проверка асинхронного теста, которая будет выполнена, вызовет done() и сообщит mocha, что весь тест завершен. Вы должны выполнить вызов done() с кодом, который подсчитывает, сколько тестов завершено, а затем называет завершение после последнего завершения.

for(var i = 0; i < arr1.length; i++){ 
    describe("Test", function(){ 
     it("Does something", function(done){ 
      var remaining = arr2.length; 
      for(var x = 0; x < arr2.length; x++){ 
       it("Does something else", function(done){ 
        // Do stuff with arr1[i], arr2[x] etc. 
        testFunc(arr1[i], arr2[x], function(returnValue){ 
         assert.strictEqual(returnValue, true, "Passed!"); 
         remaining--; 
         if (remaining === 0) { 
          done(); 
         } 
        } 
       }); 
      } 
     }); 
    }); 
} 

Это, я не знаю, поддерживает ли мокко несколько одновременных вызовов(). Возможно, вам понадобится переместить обе петли внутри него().

Мне кажется странным, что у вас есть петли для разных точек, а не рядом друг с другом, но это может быть просто результат того, что вы тестируете.

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

+0

Да, из-за того, как печатается мой описываемый текст, он должен быть после первого цикла, но до второго (неудобно я знаю). Спасибо за ответ, я вернусь к вам после того, как я попробую. – whitfin

+0

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

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