手动订阅和调用updateFromJS会导致死锁

Manually subscribe and call updateFromJS causes dead-lock

本文关键字:死锁 updateFromJS 调用      更新时间:2023-09-26

下面有一些代码,以确保用户不需要单击任何按钮并将所有输入更新到服务器端。服务器端代码负责执行任何计算并将更新的JSON发送回客户端。

这里的问题是手动订阅代码将检测用户输入的变化,它将调用一个函数将JSON数据发送到服务器并从服务器接收JSON。从这里开始,它将尝试通过调用ko.mapping.updateFromJS(viewModel, data);来更新视图模型,但是这里发生了死锁。updateFromJS将再次触发手动订阅事件,因此再次调用服务器代码,从而触发另一轮手动订阅。

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);
        }
    });
}

是否可以这样做:

  • 呼叫ko.mapping.updateFromJS时禁用手动订阅?(事后恢复)。
  • 手动订阅忽略ko.mapping.updateFromJS呼叫触发的事件?

你可以用这样的变量来做吗:

<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();
});

然后在postToServer函数

success: function (data) {
    // update JSON returned from server side to observable view-model
    preventUpdate = true;
    ko.mapping.updateFromJS(data, viewModel);
    preventUpdate = false;
}