0

このコードの何が問題になっていますか?

setInterval()止まらない。それは無限ループです。

これがビューのコードです。

var chat = require('core/chat');
var Backbone = require('backbone');
var $ = require('jquery');
var agentOfferTemplate = require('hbs!templates/agent-offer');
var contador = 20;
var intervalID;

AgentOfferView = Backbone.View.extend({


    template : agentOfferTemplate,


    initialize : function() {
        this.timeAccept();
    }, 


    render : function() {
            this.$el.append(this.template(this.model.toJSON()));
            return this;
        },

    timeAccept : function(){ 
        if (contador > 0){
            $('#tempo').html(contador); 
            $('#barra-interna').css('width', contador * 10);
            intervalID = setInterval(this.timeAccept, 1000);                
            contador = contador - 1;
        }
        else {
            window.clearInterval(intervalID);
            intervalID = null;
            $('#countdown-container').hide();
    contador = 20;                 
        }
    }

});

 return AgentOfferView;
4

2 に答える 2

1

setTimeoutまたはを使用して関数が呼び出されるとsetIntervalthisキーワードはその参照を失います (関数は新しいコンテキストで呼び出されます)。this一般的に言えば、null(厳密モードで) またはグローバル オブジェクトのいずれかを参照します。詳細については、MDNの The "this" problem
というタイトルのセクションをお読みください。基本的に、関数への参照を に渡します。これは、関数のコンテキストでその関数を呼び出します。これは明らかに...グローバルオブジェクトには明らかにメソッドがないため、タイムアウトループは実行されますが、一度ではありません20回。それはそれと同じくらい簡単です。window.setIntervalsetIntervalwindowtimeAccept
IMO の問題を回避する最も簡単な方法は、クロージャーを使用して、コンテキスト全体を interval 関数に渡すことです。ありがたいことに、簡単に修正できます。

    timeAccept : function()
    { 
        if (contador > 0)
        {
            $('#tempo').html(contador);
            $('#barra-interna').css('width', contador * 10);
            intervalID = setTimeout((function(context)
            {//pass current this reference to closure
                return function()
                {//instead of this, use context
                        setInterval(context.timeAccept, 1000);
                };
            }(this)),1000);
            contador--;
        }
        else
        {
            clearTimeout(intervalID);
            intervalID = null;
            $('#countdown-container').hide();
            contador = 20;                 
    }

間隔は、指定された関数を X ミリ秒ごとに何度も呼び出すものです。setTimoutコードを見ると、関数を 1 回だけ呼び出すを使用したいと思うでしょう。
現状では、20 の間隔を作成しており、それぞれが毎秒同じ関数を呼び出しています。であってもcontador >= 0、間隔は関数を呼び出し続けます。

次の例を検討してください。

var intervalId = setInterval(function()
{
    console.log('You\'ll see this appear every second');
    console.log('This interval has an ID, and it\'s: ' + intervalId);
},1000);

var timeout = setTimeout(function()
{
    console.log('This will only appear once, after 1000ms');
    console.log('A timeout has an ID, too: ' + timeout);
},1000);

//using the ID's you can cancel both the timeout and the interval using these lines:
clearInterval(intervalId);
clearTimeout(timeout);//usefull if you want to cancel the delayed function call...
于 2013-03-12T16:49:21.570 に答える
0

解決しました。

timeAccept : function(){ 
        var intervalId = setInterval(
            function(){
                if (contador > 0){
                    $('#tempo').html(contador); 
                    $('#barra-interna').css('width', contador * 10);
                    contador--;
                }else{
                    clearInterval(intervalId);
                    $('#countdown-container').hide();
                    contador = 20;
                }
            }, 1000);
    }

この方法は問題なく機能します。

于 2013-03-13T11:45:40.793 に答える