用作回调时的Javascript函数fire order

时间:2015-03-13 19:54:11

标签: javascript jquery promise

我创建了一个小的fetch函数,基本上只为我做了一个ajax POST以及为了简洁我已删除的其他一些东西。在这个函数中,我传递一个回调函数,该函数应该在成功回调被触发时触发。

function ajax_fetch(url, fetch, data, callback) {     

    $.ajax({
        type: "Post",
        url: baseurl + url,
        data: data,
        contentType: "application/json",
        dataType: "html",
        success: function (response) {
            fetch.html(response);

            // if there's a callback, run it.
            if (typeof callback == "function")
                callback();
        },
        error: function (xhr, ajaxOptions, thrownError) {
            handleErrors(xhr, ajaxOptions, thrownError);
        }
    });
}

下面我有一段代码,我基本上在做2个ajax调用。第一个触发正常的ajax POST,然后成功后调用上面的ajax_fetch()函数,所有函数都按预期工作。

$("#markstatus").singleBind("click", function () {
    var step = "{ step : " + $(this).data("step") + "}";

    $.ajax({
        type: "POST",
        url: baseurl + "SetStatus",
        data: step,
        contentType: "application/json",
        dataType: "html",
        success: function (result) {
            $("#header.container").html(result);
            ajax_fetch("/StepIndex", $(".replaceable"), step,
            function() {
                window.alerts.success("Step Complete");
            });              
        },
        error: function (xhr, ajaxOptions, thrownError) {
            handleErrors(xhr, ajaxOptions, thrownError);
        }
    });
});

然而问题是:

$("#removestatus").singleBind("click", function () {

    var step = "{ step : " + $(this).data("step") + "}";

    ajax_fetch("RemoveStatus", $("#header.container"), step,
        ajax_fetch("/StepIndex", $(".replaceable"), step,
        function () {
            window.alerts.warning("Step Re-Opened");
        })
    );
});

我认为我可能很棘手并且最初通过使用我的ajax_fetch()函数进行基本上相同的双ajax调用,然后在另一个ajax_fetch()中点击第一个回调传递时,所有应该是好的和花花公子。

但是当我查看我的控制台输出时:

customSpa.js:793 Object {url: "/StepIndex", fetch: jQuery.fn.init[1], data: "{ step : 1}", callbackl: function}
customSpa.js:801 requesting: /async//StepIndex
customSpa.js:793 Object {url: "RemoveStatus", fetch: jQuery.fn.init[1], data: "{ step : 1}", callbackl: undefined}
customSpa.js:801 requesting: /async/RemoveStatus

我可以看到它首先调用内部提取,然后是外部调用。这是一个异步/承诺类型的问题,或者我究竟做错了什么?

4 个答案:

答案 0 :(得分:4)

您正在尝试将函数作为回调传递(稍后调用),但是您传递立即调用函数的结果

你需要写这样的电话:

ajax_fetch("RemoveStatus", $("#header.container"), step,
    function() {
        ajax_fetch("/StepIndex", $(".replaceable"), step,
        function () {
            window.alerts.warning("Step Re-Opened");
        })
    }
);

......这应该不足为奇。内部回调是一个函数;外部回调也必须是一个函数。

答案 1 :(得分:1)

当您致电ajax_fetch时,它正在执行ajax调用。您没有将该函数作为回调传递,您在此处调用该函数:

ajax_fetch("RemoveStatus", $("#header.container"), step,
    ajax_fetch("/StepIndex", $(".replaceable"), step, // this makes the call
    function () {
        window.alerts.warning("Step Re-Opened");
    })
);

答案 2 :(得分:1)

我建议使用jQuery的Promise功能而不是深度嵌套。

因此,您将从jqXHR函数返回$.ajax来自ajax_fetch的{​​{1}}来电。在实现Promise界面时,您可以在其上调用.then,在then - 回调中,您可以进行下一次ajax_fetch调用并返回jqXHR

function ajax_fetch(url, fetch, data) {     

    return $.ajax({
        type: "Post",
        url: baseurl + url,
        data: data,
        contentType: "application/json",
        dataType: "html",
        success: function (response) {
            fetch.html(response);
        },
        error: function (xhr, ajaxOptions, thrownError) {
            handleErrors(xhr, ajaxOptions, thrownError);
        }
    });
}



$("#removestatus").singleBind("click", function () {

    var step = "{ step : " + $(this).data("step") + "}";

    ajax_fetch("RemoveStatus", $("#header.container"), step)
    .then(function() {
      return ajax_fetch("/StepIndex", $(".replaceable"), step);
    })
    .then(function() {
      window.alerts.warning("Step Re-Opened");
    });
});

答案 3 :(得分:1)

正如其他人所说,你得到错误的原因是ajax_fetch(..., ..., ..., function () {...})是函数调用,而不是函数。

此外,您正在做一些使代码不必要复杂的事情。

  • 没有必要将fetchcallback传递给ajax_fetch()。通过从函数返回$ .ajax(...)生成的jqXHR对象,任何调用函数都可以处理链式.then()中的响应,并且还处理链末尾的错误条件。
  • step不需要是手工编码的JSON字符串。它可以写为对象文字,结果对象直接用作ajax .data属性。因此,contentType: "application/json",可以消失。

你最终应该:

function ajax_fetch(url, data) {
    return $.ajax({
    ^^^^^^
        type: "POST",
        url: baseurl + url,
        data: data,
        dataType: "html"
    });
}

两个调用函数如下:

$("#markstatus").singleBind('click', function () {
    var step = { step: $(this).data('step') };
    ajax_fetch("SetStatus", step).then(function (result) {
        $("#header.container").html(result);
        return ajax_fetch("/StepIndex", step).then(function(response) {
            $(".replaceable").html(response);
        });
    }).then(function() {
        window.alerts.success("Step Complete");
    }, handleErrors);
});

$("#removestatus").singleBind('click', function () {
    var step = { step: $(this).data('step') };
    ajax_fetch('RemoveStatus', step).then(function(result) {
        $("#header.container").html(result);
        return ajax_fetch("/StepIndex", step).then(function (response) {
            $(".replaceable").html(response);
        });
    }).then(function() {
        window.alerts.warning("Step Re-Opened");
    }, handleErrors);
});

两个事件处理程序非常相似,您可以将它们组合在一起。您只需要一种机制来管理差异,即:

  • 将部分路径作为url
  • 传递给ajax_fetch()
  • 警告信息。

首先,为每个可点击元素设置一些数据。

$("#markstatus").data('params', {
    'path':'SetStatus',
    'message':'Step Complete'
});
$("#removestatus").data('params', {
    'path':'RemoveStatus',
    'message':'Step Re-Opened'
});

然后将单击处理程序附加到两个元素。

$("#markstatus, #removestatus").singleBind('click', function () {
    var $this = $(this),
        step = { 'step': $this.data('step') },
        params = $this.data('params');
    ajax_fetch(params.path, step).then(function(result) {
        $("#header.container").html(result);
        return ajax_fetch("/StepIndex", step).then(function (response) {
            $(".replaceable").html(response);
        });
    }).then(function() {
        window.alerts.warning(params.message);
    }, handleErrors);
});