2012-03-11 3 views
1

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

Это моя функция структура:

el('root', function(){ 

    el('users', function(){ 
    el('show'); 
    }); 

    el('products'); 

}); 

Результат я хочу это:

assert.equal(result, [ 'root', 'root_users', 'root_users_show', 'root_products' ]); 

я получил довольно далеко в моей реализации: http://jsfiddle.net/5ur5u/ У меня есть проблема в том, что я увеличивая свою глубину каждый раз при вызове el. Он отлично работает, пока не достигнет продуктов. Потому что шоу показывает глубину на 3, это означает, что продукты будут добавлены в конце шоу.

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

+0

Это сложно, потому что 'el' не может (в здравом образом) знать, на каком уровне он был вызван. Возможно, вам лучше передать функцию 'el' на обратный вызов, который будет отличаться каждый раз. – pimvdb

+0

Вы имеете в виду el ('root', function (el) {el ('users')}) ;? – Pickels

+0

Да - см. Мой ответ. – pimvdb

ответ

1

Это делает то, что вы просите

var names = []; 
var result = []; 

function el(name, f) 
{ 
    names.push(name); 
    result.push(names.join("_")); 
    f && f(); 
    names.pop(); 
} 

el("root", function(){ 
    el("users", function(){ 
     el("show") 
    }); 
    el("products"); 
}); 

alert(result); 
+0

Бах, так гордился тем, что у меня было, но это в миллион раз лучше. – Pickels

1

Так как el это та же функция, каждый раз, когда она называется, нет никакого способа отличить его называют в одном уровне (show) или другой (products). Вы можете увеличивать уровень каждый раз, когда вызывается el, но нет способа узнать, когда его уменьшить, потому что нет никакого «противоположного» вызова в JavaScript.

Немного лучший вариант - передать новую функцию обратному вызову (вы можете дать ему то же имя el), что отличается от того, что каждый уровень имеет свою собственную функцию el. Таким образом, результат может быть построен правильно: http://jsfiddle.net/5ur5u/2/.

var result = []; 

function el(name, fn) { 
    result.push(name); // add current name 

    if(fn) { // if there is a function 
     fn(function(name2, fn2) { // call the function with a new function 
      el(name + "_" + name2, fn2); // which calls `el` recursively 
             // with the names combined 
     }); 
    } 
} 

el('root', function(el) { 

    // this `el` refers to the function passed as declared above, 
    // which is not the same one as the initial `el` 
    el('users', function(el) { 
    el('show'); 
    }); 

    el('products'); 

}); 
+0

+1 Мне нравится, как ваше решение упрощает библиотечный код, но делает карту url немного более подробной (дополнительный параметр el). – Pickels

2

Вы очень близко. Вам просто нужно уменьшить глубину в конце. См http://jsfiddle.net/Z2qsy/

Вместо

depth += 1; 
fn(); 

ли это

depth += 1; 
fn(); 
depth -= 1; 
+0

+1 Это отлично работает; Я не обратил на это внимания. – pimvdb

+0

Подумайте, вы забыли нажать обновление в jsfiddler. Вот ссылка с рабочим примером с вашим патчем. http://jsfiddle.net/Z2qsy/1/ – Pickels

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