MVC: Telling the controller to stop
I'm experimenting with javascript and MVC models. I want to (simplified example) move an object across the screen a random number of pixels between 1 and 10 and then have it stop when it gets to, say, 400 pixels.
The view
is set up to observe the model
, which has a notifyObservers()
function.
When the start button on the view
is clicked it sends a startButtonClicked
message to the controller
.
controller.startButtonClicked = function () {
var animate = function () {
controller.getModel().shift(); // get the model and run the shift() function
setTimeout(animate, 20);
};
animate();
}
This runs the model
's shift()
function:
model.shift = function () {
if(model.x < 400) {
model.x += Math.floor(Math.random()*11); // Add up to 10 pixels
}
model.notifyObservers(); // Tells view to update,
};
This works fine, and the object stops at around 400 pixels as it should. However, the setTimeout loop in controller.startButtonClicked()
is still whirring away.
[Edit: As I understand it, the traditional MVC model doesn't allow the model
to communicate with the controller
directly, so the model can't just tell the controller to stop the timer.]
So, finally to the question: How do I make the loop in the controller stop?
The possible solutions I've thought of:
- Get the model to tell the view, which then t开发者_如何学Goells the controller. But that seems very long-winded.
- Get the controller to ask the model if it's done. But that seems to go against the MVC structure.
- Get the
shift()
function to returnfalse
to the controller when it's done.
Anyone who's been doing MVC for a while know what the right way of doing it would be?
Thanks!
Something like this:
var t; // feel free to make this a non global variable
controller.startButtonClicked = function () {
var animate = function () {
controller.getModel().shift(); // get the model and run the shift() function
t = setTimeout(animate, 20);
};
animate();
}
model.shift = function () {
if(model.x < 400) {
model.x += Math.floor(Math.random()*11); // Add up to 10 pixels
}
else {
clearTimeout(t);
}
model.notifyObservers(); // Tells view to update,
};
You need to use clearTimeout(arg)
where arg
is the return value from a setTimeout
call.
Also, be careful with low (< 50) values for setTimeout(), what you have coded calls animate 50 times per second.
controller.startButtonClicked = function () {
var animate = function () {
var m = controller.getModel();
m.shift(controller); // get the model and run the shift()
m.timerInterval = setTimeout(animate, 20);
};
animate();
}
model.shift = function () {
if(model.x < 400) {
model.x += Math.floor(Math.random()*11); // Add up to 10 pixels
}
else if (model.timerInterval)
{
clearTimeout(model.timerInterval);
}
model.notifyObservers(); // Tells view to update,
};
精彩评论