为什么这个 setTimeout 根本不触发?

Why doesn't this setTimeout fire at all?

我正在使用 Knockout js,我一定遗漏了一些非常概念化的东西。我没有收到错误,所以我很难理解我哪里出错了。我只是想每隔 X 秒提取一次数据,然后用该数据重新填充我的 table。我正在使用 Knockout js 进行绑定。此示例代码应该足以显示问题:

            function AppViewModel() {
            var self = this;
            self.servers = ko.observableArray([{ Name: 'Loading...', Url: 'Loading...', Environment: 'Loading...', Health: 'Loading...' }]);
            self.refreshServers = function () {
                $.ajax({
                    url: '@Url.Action("GetData", "Temp")',
                    data: { id: 1 },
                    type: 'POST',
                    success: function (data) {
                        self.servers(data);
                        console.log("finished loading data");
                    }
                });
            };
            self.refreshServers();
            setInterval(self.refreshServers, 15000);
        }
        ko.applyBindings(fViewModel);

我直接调用函数self.refreshServers一次来立即填充数据(也许有更好的方法来做到这一点?)然后我设置超时以连续调用。我从未见过第二个 ajax 请求或第二个日志功能。

函数以 () 结尾,因此在这种情况下,您的函数可能被称为 refreshServers()。另请注意,您将计时器设置为 15 秒,恕我直言,这个时间很长。

setTimeout(self.refreshServers, 15000); 在调用 AppViewModel() 时立即 运行ning。

如您所说,它会立即 运行,因为它需要 function(){} 作为参数才能在所需的 15 秒后实际执行。

试试这个:

....
setTimeout(function(){
    self.refreshServers();
}, 15000);
.....

**
在这里要小心; setIntervalsetTimeout 不同。

setInterval 将 运行 在给定的时间间隔内周期性地 运行 一段或一段代码,而 setTimeout 将 运行 它仅一次(或者更确切地说每次 AppViewModel() 被调用)。正如你所说,你的代码 运行 一次,但可能在你真正想要它之前 运行.

感谢@kinakuta 和@Marin Smit 指出我未能理解的显而易见的地方。我显然太快地读到了 setInterval 和 setTimeout 之间的区别。

两种解决方案是加括号,由setTimeout改为setInterval

实际上这里有一些问题。

首先,根据您对问题的描述,您可能想要 'setInterval()' 而不是 'setTimeout()'。不同的是'setInterval()'会按照一定的时间间隔连续执行,而'setTimeout()'会在时间到后只执行一次。

第二个问题是,正如其他人提到的,第一次调用 'self.refreshServers()' 确实需要括号才能执行第一次调用,而 'setInterval()' 中的引用不应该有括号。这是因为在 'setInterval()' 中,您传递的是对将要执行的函数的引用,而不是已执行函数的结果。

减去 AJAX,这是一个基于您的代码的工作示例:

function AppViewModel() {
    var self = this;
    self.numberOfIntervals = 0;

    self.servers = ko.observableArray([{
        Name: 'Loading...',
        Url: 'Loading...',
        Environment: 'Loading...',
        Health: 'Loading...'
    }]);

    self.refreshServers = function () {
        // AJAX GOES HERE... THEN UPDATE RESULTS
        self.servers.push({
            Name: 'New Name...' + self.numberOfIntervals,
            Url: 'New Url...' + self.numberOfIntervals,
            Environment: 'New Enviornment...' + self.numberOfIntervals,
            Health: 'New Health...' + self.numberOfIntervals
        });

        self.numberOfIntervals++;
    };

    self.refreshServers();
    setInterval(self.refreshServers, 3000);
}

ko.applyBindings(AppViewModel);

这是一个可用的 fiddle 来玩:http://jsfiddle.net/dunka494/4/

希望对您有所帮助!