Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Jquery何时和延迟对象,函数流中断_Javascript_Jquery_Jquery Deferred_.when - Fatal编程技术网

Javascript Jquery何时和延迟对象,函数流中断

Javascript Jquery何时和延迟对象,函数流中断,javascript,jquery,jquery-deferred,.when,Javascript,Jquery,Jquery Deferred,.when,我使用$.when和.done来确保在保存数据后关闭窗口。但是,这似乎并不像预期的那样有效 工作流程是,用户单击“保存并关闭”按钮,首先保存数据,触发打印并关闭窗口。但保存数据和关闭窗口同时发生,导致打印失败 我已经读过关于什么时候…然后和推迟的对象。尝试在下面的代码中实现它,有时它可以工作,但大多数时候它会中断 $("#btnSaveAndClose").click(function (event) { $.when(zSaveSomeData()).done(function (va

我使用$.when和.done来确保在保存数据后关闭窗口。但是,这似乎并不像预期的那样有效

工作流程是,用户单击“保存并关闭”按钮,首先保存数据,触发打印并关闭窗口。但保存数据和关闭窗口同时发生,导致打印失败

我已经读过关于什么时候…然后和推迟的对象。尝试在下面的代码中实现它,有时它可以工作,但大多数时候它会中断

$("#btnSaveAndClose").click(function (event) {
    $.when(zSaveSomeData()).done(function (value) {
        zCloseMyWindow();
    });
});

function zSaveSomeData() {
    return zSaveMasterData(masterdata, function () {  
        return zSaveDetailData();
    });
};

function zSaveMasterData(masterdata, fnAfterSave) {
    return $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: '/api/masterdata/',
        data: JSON.stringify(masterdata),
        success: function (data) {
            fnAfterSave();
        }
    });
};

function zSaveDetailData() {
    var selectedDataGroups;
    // some logic here

    zSaveDetails(selectedDataGroups);

};

function zSaveDetails(selectedDataGroups) {
    var deferred = $.Deferred();
    $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: '/api/detaildata/',
        data: JSON.stringify(selectedDataGroups),
        success: function (data) {
            var printableGroupIDs = [];
            $.each(data, function () {
                if (this.IsPrintable)
                    printableGroupIDs.push(this.ID);
            });

            if (printableGroupIDs.length > 0) {
                zPrintGroups(printableGroupIDs);
            }
            deferred.resolve('done');
        }
    });

    zAuditSave();
    return deferred.promise();
};

function zPrintGroups(newGroupIDs) {
    // calls external program to print groups

};

function zCloseWindow() {
    window.close();
};

function zAuditSave() {
    $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: '/api/audit'
        success: function (data) {

        }
    });
};

唯一的问题是save调用内部的其他方法来处理相同的主数据和详细数据。还有几个ajax调用。一个不寻常的事情是,数据保存后,会调用VB代码,实际触发打印。我很困惑为什么要在其他方法执行之前关闭窗口。任何帮助都将不胜感激。

这里的问题是您的代码不取决于
fnaturave()
何时完成

简短回答:不要混合使用
成功
方法、
回调
承诺
——使用一种模式并坚持下去——最简单的模式是
承诺

$("#btnSaveAndClose").click(function (event) {
    zSaveSomeData().then(function() { zCloseMyWindow(); });
});

function zSaveSomeData() {
    return zSaveMasterData(masterdata).then(function(data) { zSaveDetailData() });
};

function zSaveMasterData(masterdata) {
    return $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: '/api/masterdata/',
        data: JSON.stringify(masterdata)
    });

    //remove success callback here as it breaks the chaining
};

您的问题似乎是在ajax
success
回调中执行异步操作。
$.ajax
返回的承诺仍然会在收到响应后立即解析,并在异步
zSaveDetailData()
完成之前执行
done
回调

因此,要链接异步操作,请始终使用
then
。即使在同步操作中也要使用它,因为它可以使顺序变得清晰

在处理承诺时,不要使用
success
回调。你也是。您可能还想看一看,尤其是永远不要忘记
从想要等待的异步函数返回
承诺

$("#btnSaveAndClose").click(function (event) {
    zSaveSomeData().then(zCloseMyWindow);
});

function zSaveSomeData() {
    return zSaveMasterData(masterdata).then(zSaveDetailData);
}

function zSaveMasterData(masterdata) {
    return $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: '/api/masterdata/',
        data: JSON.stringify(masterdata),
    });
}

function zSaveDetailData() {
    var selectedDataGroups;
    // some logic here

    return zSaveDetails(selectedDataGroups);
//  ^^^^^^
}

function zSaveOrderGroups(selectedDataGroups) {
    return $.ajax({
//  ^^^^^^
        type: 'POST',
        contentType: 'application/json',
        url: '/api/detaildata/',
        data: JSON.stringify(selectedDataGroups)
    }).then(function(data) {
//    ^^^^^^^^^^^^^^^^^^^^^^
        var printableGroupIDs = [];
        $.each(data, function () {
            if (this.IsPrintable)
                 printableGroupIDs.push(this.ID);
        });
        if (printableGroupIDs.length > 0) {
            return zPrintGroups(printableGroupIDs);
//          ^^^^^^
        }
    }).then(zAuditSave);
//    ^^^^^^^^^^^^^^^^^
}

function zPrintGroups(newGroupIDs) {
    // calls external program to print groups
}

function zCloseWindow() {
    window.close();
}

function zAuditSave() {
    return $.ajax({
//  ^^^^^^
        type: 'POST',
        contentType: 'application/json',
        url: '/api/audit'
    });
}

对我来说,代码被过度地划分为多个函数,有些函数只不过是为另一些函数做前置

我更愿意将click处理程序视为一个全面的主例程,它对三个函数进行排序,
zSaveMasterData()
zSaveDetails()
zAuditSave()
,然后关闭窗口。因此,单击处理程序将包含一些当前函数

$("#btnSaveAndClose").click(function(event) {
    zSaveMasterData(masterdata).then(function() {
        var selectedDataGroups;
        /* some logic here */
        var detailsSaved = zSaveDetails(selectedDataGroups).then(function(data) {
            var printableGroupIDs = $.map(data, function (obj) {
                return obj.IsPrintable ? obj.ID : null;
            });
            if (printableGroupIDs.length > 0) {
                // calls external program to print groups
            }
        });
        // Here, it is assumed that zSaveDetails() and zAuditSave() can be performed in parallel.
        // If the calls need to be sequential, then the code will be slightly different.            
        return $.when(detailsSaved, zAuditSave());
    }).then(function() {
        window.close();
    });
});

function zSaveMasterData(masterdata) {
    return $.ajax({
        type: 'POST',
        url: '/api/masterdata/',
        contentType: 'application/json',
        data: JSON.stringify(masterdata),
    });
};

function zSaveDetails(selectedDataGroups) {
    return $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: '/api/detaildata/',
        data: JSON.stringify(selectedDataGroups)
    });
};

function zAuditSave() {
    return $.ajax({
        type: 'POST',
        contentType: 'application/json',
        url: '/api/audit'
    });
};
注意使用ajax调用的三个函数中的返回。这些返回对排序过程至关重要


一个潜在的更大的问题是如何从错误中恢复,这一点在问题(或本答案)中没有提到。据推测,如果保存顺序中途失败,数据库将不一致。最好放弃这种客户端排序方法,转而使用客户端视为单个操作的服务器端事务。

return zSaveDetailData();zCleanUp()-等等什么?什么是
zAuditSave()
?@Bergi,谢谢你指出这一点,实际上这段代码是我编辑时留下的。它不在那里。我添加了return to test,但确实清理了代码。
zAuditSave()
是另一种调用webApi进行审计保存的方法。我也将添加该方法。我尝试重构代码,以仅使用一种模式,即
承诺
。仍然在
zPrintGroups()
之前调用
zCloseWindow()
。我试着调试,发现控件点击了行
returnzsavedetails(selectedDataGroups)然后当我进入时,执行带有in
zSaveDetails()
的ajax来保存数据,然后控件直接转到
zCloseWindow()
并关闭窗口,因此
zSaveDetails()
中的
zPrintGroups()
方法永远不会被触发。也许你已经得到了
然后(zCloseWindow())
而不是
。然后(zCloseWindow)
?我交叉检查,它是
zSaveSomeData()。然后(zCloseWindow)。我还检查了所有其他的方法调用,它们看起来不错。你能在什么地方放一个演示吗?我很有信心这会奏效。当然,我会尝试创造一些可演示的东西。但不知道如何进行ajax调用。但是,让我试试。我认为你使用
$.map
不起作用,though@Bergi,我的代码都没有经过测试,我很可能会犯错误。从内存来看,
jQuery.map()
不同于
Array.prototype.map()
,因为jQuery版本(a)在返回null时过滤掉一个元素,(b)返回一个jQuery包装的数组(因此需要.get())。是的,它应该被命名为
concatMap
,因为它处理
null
和数组值。但是实际上返回数组,而
$(arr).map(fn)
返回jquery包装器。啊,好的,我应该首先查找它。文档还指出,“在函数中,
引用全局(窗口)对象”。哎呀,编辑。谢谢你的帮助。