3

我对定义函数和实例化对象的顺序有疑问,请参阅:JSFiddle

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

  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 
    }
  });

谢谢你的帮助。

4

4 回答 4

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.
于 2013-02-10T01:06:40.063 回答
1

您可以使用 atry/catch来避免第一个未定义:

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

此外,如果您在 JSFiddle 中测试所有内容,它会将您的 JS 包装到一个window.onload函数中。因此,当您单击按钮时,它们将尝试调用fsm.back()or fsm.next(),其中fsm在该函数的范围内定义window.onload。不在这些按钮可以访问的范围内。

于 2013-02-10T01:26:55.703 回答
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();
}

小提琴

于 2013-02-10T05:19:29.753 回答
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),
}
于 2013-02-10T06:10:32.080 回答