中止 AJAX 请求链 jQuery 延迟

Abort chain of AJAX requests with jQuery deferred

我正在进行一系列 AJAX 调用,如下例所示,我在 http://www.dotnetcurry.com/jquery/1022/jquery-ajax-deferred-promises.

找到了

如果 函数 A[=22 中的 AJAX 调用的响应,我如何调整代码以防止调用 函数 B =] 是一个空的 JSON 对象数组(即“[ ]”)?理想情况下,我不仅要中止 AJAX 调用链,还要通知用户未找到结果。

谢谢!

function A() {
    writeMessage("Calling Function A");
    return $.ajax({
        url: "/scripts/S9/1.json",
        type: "GET",                    
        dataType: "json"
    });
}


function B(resultFromA) {
    writeMessage("In Function B. Result From A = " + resultFromA.data);
    return $.ajax({
        url: "/scripts/S9/2.json",
        type: "GET",
        dataType: "json"
    });
}


function C(resultFromB) {
    writeMessage("In Function C. Result From B =  " + resultFromB.data);
    return $.ajax({
        url: "/scripts/S9/3.json",
        type: "GET",
        dataType: "json"
    });
}

function D(resultFromC) {
    writeMessage("In Function D. Result From C = " + resultFromC.data);
}

A().then(B).then(C).then(D);

function writeMessage(msg) {
    $("#para").append(msg + "<br>");                 
}

一般来说,您可以使每个工作函数 A、B、C、D return 成为一个对象,其中包含响应数据以及是否要继续调用链中的下一个函数,无论如何那可能。像这样:

function A(input) {
    return $.get("/scripts/S9/1.json").then(function (response) {
        return {
            continue: response.data && response.data.length,
            data: response
        };
    });
}

现在你可以通过减少一组工作函数来创建一个承诺链,并在每一步中决定你是否要继续(在这种情况下你执行下一个工作人员)或不(你只需要保持 return为链的其余部分获取最后一个有效结果)。由于缺少更好的名称,我已将此逻辑包装到一个函数中 breakableChain

function maybe() { return Math.random() > 0.25; }
function A(input) { console.log('in A:', input.data); return {continue: maybe(), data: 'result from A'}; } 
function B(input) { console.log('in B:', input.data); return {continue: maybe(), data: 'result from B'}; } 
function C(input) { console.log('in C:', input.data); return {continue: maybe(), data: 'result from C'}; } 
function D(input) { console.log('in D:', input.data); return {continue: maybe(), data: 'result from D'}; } 

function breakableChain(workers, init) {
    return workers.reduce(function (current, next) {
        return current.then(function (result) {
            return result.continue ? next(result) : result;
        });
    }, $.Deferred().resolve({continue: true, data: init}));
}

breakableChain([A, B, C, D], 'initial data').then(function (result) {
    console.log('overall:', result.data);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

当然你可以制作一个不需要 continue 标志的非通用版本,而是将关于每个结果的假设直接硬编码到里面的 if 语句中.reduce()。那会更短,但不能重复使用。

整个{continue: true, data: result}事情只是一个惯例。你的约定也可以是"if the previous call returned anything, then continue, otherwise stop",方法是一样的,但是不可能return一个整体的结果。