全局(窗口)变量在Emberjs中表现得很奇怪

时间:2016-11-18 13:59:08

标签: javascript ember.js

我在我的网络应用中使用Ember-cli。我有一个倒计时组件来显示UI上的倒数计时器。这是我的组件代码。

export default Ember.Component.extend({
    end_time: 0,
    start_time: 0,
    some_id: 0,
    timer: 0, // Show this in UI - {{timer}} Seconds

    init: function() {
        this._super();
        let end_time = this.get("end_time"),  // 1479476467693
            start_time = this.get("start_time"), // 1479476381491
            some_id = this.get("some_id");
        let wait_time = Math.floor((end_time - start_time)/1000);
        this.set('timer', wait_time);
        let timerName = "timer_" + some_id;
        let _self = this;
        window.initTimer.someTimer[timerName] = setInterval(function() {
            _self.set('timer', wait_time);
            if(wait_time <= 0) {
                clearInterval(window.initTimer.someTimer[timerName]);
            }
            wait_time --;
        }, 1000);
    }
});

如果将此组件添加到单个路径,此组件可正常工作。

现在,我已将此组件添加到父路由和子(/:ID)路由,因为我需要在两个模板上显示该组件。在子(/:ID)模板中,我有一个清除计时器的按钮。所以我为该按钮动作添加了这段代码。

buttonAction: function(some_id) {
            let timerName = "timer_" + some_id;
            clearInterval(window.initTimer.someTimer[timerName]);
        }

奇怪的是,当调用buttonAction时,仅清除子模板上的计时器。父模板上的计时器继续运行。但是,两个计时器都分配给一个全局变量(window.initTimer.someTimer),并且应该在运行clearInterval()时清除。

是否有任何解决方案可以在点击按钮时清除父路线和子路线上的定时器,该按钮位于子模板上?无法弄清楚Ember在玩全局变量的魔力是什么!!

1 个答案:

答案 0 :(得分:1)

Ember在这里没有任何魔力,但你的代码很多变得复杂!

有趣的问题是来自some_id的地方。如果对于两者都不一样,那么你打电话给buttonAction

假设您有ids onetwo。然后,您在window.initTimer.someTimer.timer_onewindow.initTimer.someTimer.timer_two处有两个时间间隔。现在,如果您清除window.initTimer.someTimer.timer_one,为什么还要清除window.initTimer.someTimer.timer_two?好吧,它不是,这就是为什么你的代码不起作用。

假设您只有一个ID,请为两个计时器调用theOnlyOne。 然后,第二个组件的init挂钩将重新分配window.initTimer.someTimer.timer_theOnlyOne,因此当您致电buttonAction时,只能重置此第二个组件。那就是为什么你的代码无效。

那你现在该怎么办?首先,你真的应该停止使用全局对象!在ember生态系统中有更好的方法可以做到这一点。

对于您的计时器,您应该查看ember-concurrency

如果要使用全局状态,则应使用service。但是,我不建议您解决这个问题,因为它违反了DDAU原则。然而,为了告诉你最好的方法来做你想做的事情,我们需要了解为什么你有这个定时器,它们是如何相关的,以及你想要一键取消它们的原因。可能你会在组件之外有一些计时器状态并将其传递给组件。也许util可能会有所帮助。但这实际上取决于你的用例。