假设我有一台服务器,每次客户端的数据发生变化时都会向其客户端发送数据。客户端类看起来像这样:
function Client() {
this.data = {};
this.update = function (key, value) {
this.data[key] = value;
this.emitUpdate();
};
this.emitUpdate = function () {
// tell server to send this client's data
};
}
var myClient = new Client();
如果我改变了一件事:
myClient.update("name", "John");
服务器使用此客户端的新信息更新所有客户端。大。
如果我从我的应用中的不同位置一次更改多个内容:
if (something === true) {
myClient.update("something", true);
} else {
myClient.update("something_else", true);
}
myClient.update("age", Date.now());
总会有两件事发生变化,emitUpdate()
会被调用两次。服务器将发送两次数据,所有客户端都必须渲染两次。想象一下100次发生的变化......考虑到服务器只发送一次更新,这将是一个很大的开销,因为所有这些变化都发生在一个时间范围内。
如何在每个调用堆栈中仅调用emitUpdate()
一次?我使用underscore.js并检查了defer()
和throttle()
函数。问题是,我需要将它们的效果结合起来。
var log = function () {
console.log("now");
};
// logs "now" 10 times
for (let i = 0; i < 10; i++) {
_.defer(log);
}
// logs "now" 10 times
var throttled = _.throttle(log, 0);
for (let i = 0; i < 10; i++) {
throttled();
}
如果throttle()
使用wait
1
或2
等// logs "now" once
var magic = _.deferottle(log);
for (let i = 0; i < 10; i++) {
magic();
}
,则结果不一致 - 有时会调用一次,有时会更多。
我需要这样的东西:
# combine the time series actual and forcasted values
combined <- cbind(predicted, actual=ldeaths)
# plot the different values as different series
dygraph(combined , main = "Predicted Lung Deaths (UK)") %>%
dyAxis("x", drawGrid = FALSE) %>%
dySeries("actual", label = "actual") %>%
dySeries(paste0("predicted.", c("lwr", "fit", "upr")), label = "Predicted") %>%
dyOptions(colors = RColorBrewer::brewer.pal(3, "Set1"))
有没有办法实现呢?
答案 0 :(得分:2)
这适用于update()
方法的多个同步调用:
function Client() {
this.data = {};
this.update = function (key, value) {
this.data[key] = value;
if (!this.aboutToUpdate) {
this.aboutToUpdate = setTimeout(() => {
this.aboutToUpdate = false
this.emitUpdate()
})
}
};
this.emitUpdate = function () {
// tell server to send this client's data
console.log('update sent', this.data)
};
}
// This should only log 'update sent' once
var client = new Client()
for (var i = 0; i < 5; i++) {
client.update(i, i)
}
&#13;
答案 1 :(得分:2)
实际上你不需要throttle
,只需将defer
与一些布尔标志检查结合使用。
这样的事情:
this.update = function (key, value) {
this.data[key] = value;
if (this.isQueued) return;
this.isQueued = true;
_.defer(function () {
this.isQueued = false;
this.emitUpdate();
}.bind(this));
};
答案 2 :(得分:0)
洗澡时脑袋里浮现出一种解决方案:
var deferottle = function(func) {
var called, args, ctx;
return function() {
args = arguments;
ctx = this;
if (!called) {
called = true;
setTimeout(function() {
func.apply(ctx, args);
called = false;
});
}
};
};
var magic = deferottle(function(num) {
console.log("num: ", num);
});
for (let i = 0; i < 10; i++) {
magic(i);
}
结果debounce()
等待0
也可以使用:
var magic = _.debounce(function(num) {
console.log("num: ", num);
}, 0);
for (let i = 0; i < 10; i++) {
magic(i);
}
<script src="http://underscorejs.org/underscore-min.js"></script>