Manually subscribe and call updateFromJS causes dead-lock
I have some code below to make sure that a user does not need to click any button and update all input to server side. Server side code is responsible to perform any calculation and send updated JSON back 开发者_开发问答to client.
The issue here is that manual subscription code will detect the user input change, it will call to a function to post JSON data to server and receive JSON from server. From this point it will try to update the view model by calling ko.mapping.updateFromJS(viewModel, data);
, but a dead-lock happens here. The updateFromJS
will trigger the manual subscription event again, thus server code is called again, which triggers another round of manual subscription.
var initialData = /* get JSON from server side */;
var viewModel = ko.mapping.fromJS(initialData);
ko.applyBindings(viewModel, document.body);
viewModel.Product.Parameter1.subscribe(function(newValue) {
postToServer();
});
viewModel.Product.Parameter2.subscribe(function(newValue) {
postToServer();
});
viewModel.Product.Parameter3.subscribe(function(newValue) {
postToServer();
});
function getProduct() {
// retrieve JSON data to be posted to server side
}
function postToServer() {
var product = getProduct();
$.ajax({
url: '/Home/ProductUpdate/',
data: JSON.stringify(product),
type: "POST",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
// update JSON returned from server side to observable view-model
ko.mapping.updateFromJS(viewModel, data);
}
});
}
Is it possible to do either of following:
- Disable manual subscribe while
ko.mapping.updateFromJS
is called? (Resuming afterwards). - Have manual subscription ignore the event triggered by a
ko.mapping.updateFromJS
call?
Could you do it with a variable like so:
<script language="javascript" type="text/javascript">
var initialData = /* get JSON from server side */;
var viewModel = ko.mapping.fromJS(initialData);
var preventUpdate = false;
ko.applyBindings(viewModel, document.body);
viewModel.Product.Parameter1.subscribe(function(newValue) {
if (!preventUpdate) postToServer();
});
and then in the postToServer
function
success: function (data) {
// update JSON returned from server side to observable view-model
preventUpdate = true;
ko.mapping.updateFromJS(data, viewModel);
preventUpdate = false;
}
精彩评论