2013-02-10 3 views
3

У меня возникли проблемы с порядком определения функций и экземплярами объектов, см: JSFiddleJavaScript: Порядок определения функций и экземпляров объектов

Я просто играл с идеей прямо сейчас, но я ударил эту стену и я не знаю, есть ли какое-либо простое решение проблемы. В основном у меня есть объект с некоторыми методами для другого объекта, но этот другой объект содержит ссылки на первый объект, поэтому независимо от того, какой порядок я создаю/определяю, я получаю сообщение об ошибке, потому что тот или другой не был загружен:

var router = { 
    update: function(event, from, to) { 
     window.location.hash = "#/" + to; 
     $("back-btn").disabled = fsm.can("back"); // *** And here I am referencing fsm 
     $("next-btn").disabled = fsm.can("next"); 
    }, 
    location: window.location.hash.substring(2), 
    } 

    var fsm = StateMachine.create({ 
    initial: "intro", 
    events: [ 

     // Next events and where to route based on our page 
     { name: "next", from: "intro", to: "getname" }, 
     { name: "next", from: "getname", to: "welcome" }, 
     { name: "next", from: "welcome", to: "why" }, 

     // We can't go "back" from the initial route 
     { name: "back", from: "getname", to: "intro" }, 
     { name: "back", from: "welcome", to: "getname" }, 
     { name: "back", from: "why", to: "welcome" } ], 

    callbacks: { 
     onintro : router.update, //*** Here I am referencing the router object 
     ongetname: router.update, 
     onwelcome: router.update, 
     onwhy : router.update 
    } 
    }); 

Благодарим за любую помощь.

+1

Возможный дубликат http://stackoverflow.com/questions/1450997/resolving-circular-dependencies-with-dependency-injection Кроме того, здесь хороший вопрос для проверки относительно require.js http://stackoverflow.com/questions/12639772/solving-circular-dependency-in-node-using-requirejs – mrk

+0

Выполняете ли вы все это в рамках JSFiddle, или вы тестирование в другом месте? – daleyjem

+0

Я тестирую в своем браузере без области JSFiddle – nak

ответ

1

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

var fsm = StateMachine.create({ 

    //*** Here we set defer to true 
    initial: { state: "intro", event: "init", defer: true }, 
    events: [ 

    // Next events and where to route based on our page 
    { name: "next", from: "intro", to: "getname" }, 
    { name: "next", from: "getname", to: "welcome" }, 
    { name: "next", from: "welcome", to: "why" }, 

    // We can't go "back" from the initial route 
    { name: "back", from: "getname", to: "intro" }, 
    { name: "back", from: "welcome", to: "getname" }, 
    { name: "back", from: "why",  to: "welcome" } ], 
}); 

window.onload = function() { 
    var router = { 
    update: function(event, from, to) { 
     window.location.hash = "#/" + to; 
     $("back-btn").disabled = fsm.cannot("back"); 
     $("next-btn").disabled = fsm.cannot("next"); 
    }, 
    location: window.location.hash.substring(2), 
    } 

    //*** And now we attach the callbacks since we have created the router object 
    fsm.onintro = router.update, fsm.ongetname = router.update, 
    fsm.ongetname = router.update, fsm.onwelcome = router.update, 
    fsm.onwhy = router.update; 

    //*** And call the init event! 
    fsm.init(); 
} 

и fiddle

+0

Хм ... Похоже на хак, не так ли. =/Мое последнее редактирование не работает для вас? – wxactly

1

Похоже, что проблема синхронизации связана с тем, что один из обратных вызовов, которые вы указываете, - onintro, который предположительно запускается сразу. Практично ли рефакторинг вашей реализации для обратного вызова onintro? Вы можете быть в состоянии уйти с чем-то вроде этого:

var router = { 
    update: function(event, from, to) { 
     window.location.hash = "#/" + to; 
     $("back-btn").disabled = fsm.can("back"); 
     $("next-btn").disabled = fsm.can("next"); 
    }, 
    location: window.location.hash.substring(2), 
} 

var fsm = StateMachine.create({ 
    //... 

    callbacks: { 
     //onintro : router.update, // Don't call this in the constructor... 
     ongetname: router.update, 
     onwelcome: router.update, 
     onwhy : router.update 
    } 
}); 

router.update(); // Call it just after construct. 
+0

, он действительно выдает ошибку, прежде чем он даже попытается выполнить обратный вызов, поэтому, когда я прокомментирую это, она дает ошибку, вот еще JSFiddle JSFiddle с новой версией, которая работает: http: //jsfiddle.net/Yqdj5/1/ – nak

1

Вы можете использовать try/catch, чтобы избежать первого неопределенными:

try { 
    $("back-btn").disabled = fsm.can("back"); 
    $("next-btn").disabled = fsm.can("next"); 
} catch(e){} 

Кроме того, если вы тестируете все в JSFiddle, это будет чтобы превратить JS в функцию window.onload. Поэтому, когда вы нажимаете кнопки, они будут пытаться вызвать fsm.back() или fsm.next(), где fsm был определен в рамках этой функции window.onload. Не в пределах области, к которой доступны эти кнопки.

0

затруднительного положения зависимости может быть так просто, как:

var router = { 
    update: function(event, from, to) { 
     window.location.hash = "#/" + to; 
     if(window.fsm) { 
      $("back-btn").disabled = fsm.can("back"); 
      $("next-btn").disabled = fsm.can("next"); 
     } 
    }, 
    location: window.location.hash.substring(2), 
} 
+0

Ах, если бы я это сделал, кнопка была бы включена и позволяла бы пользователю сначала получить доступ к кнопке «Назад», когда они этого не сделают. Спасибо за всю помощь/идеи, но мне кажется, что мне придется отложить инициализацию FSM, назначить обратные вызовы, а затем инициализировать FSM, это единственный способ, который я могу видеть до сих пор без ошибок. Это просто проверить идею, так или иначе, ничего, что поражает широкую аудиторию (я не думаю!) – nak