2013-02-10 63 views
3
我有定义函数和实例对象的顺序问题

的顺序,请参阅:JSFiddle的JavaScript:定义函数和实例化对象

我只是一个想法玩耍的权利,但我打这堵墙我不知道是否有任何简单的解决方案。基本上我有一个对象与另一个对象的一些方法,但这个其他对象包含对第一个对象的引用,所以无论我实例化/定义的顺序,我会得到一个错误,因为一个或另一个尚未加载:

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 2013-02-10 01:06:26

+0

你所有的jsfiddle的范围内这样做,或者是你测试其他地方? – daleyjem 2013-02-10 01:23:00

+0

我测试在我的浏览器没有的jsfiddle范围 – nak 2013-02-10 01:55:01

回答

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 2013-02-10 05:23:19

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 2013-02-10 05:34:36

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(),其中fsmwindow.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,分配回调,然后初始化状态机,这是我目前可以看到,而不必错误的唯一方法。无论如何,这只是为了测试一个想法,没有什么会打击广泛的受众(我不认为!) – nak 2013-02-11 22:07:47