2015-03-13 101 views
1

我創建了一個小取指令函數,基本上爲我做了一個ajax POST以及爲簡潔起見刪除了一些其他的東西。在這個函數中,我傳遞了一個回調,當成功回調被觸發時它應該會觸發。作爲回調函數使用時,Javascript函數的火順序

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,然後成功後,調用我上面的​​函數,所有工作都按預期進行。

$("#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調用,然後在命中第一回調通另一個​​都應該是好的,花花公子。

但是,當我看到我的控制檯輸出:

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 

我可以看到它在調用內首先提取,然後在外。這是一個異步/承諾類型的問題,或者我究竟做錯了什麼?

+0

什麼是'singleBind()'?這聽起來應該與[.one()](http://api.jquery.com/one/)相同。 – 2015-03-14 13:17:00

+0

是singleBind()是我添加自己做的只是一個.off()和.on()這樣,如果我重新綁定一個處理程序後,它不會觸發多次的ajax事件...看起來像JQ已經照顧通過.one(),去圖,每當我做我認爲是聰明的,它已經完成:) – 2015-03-15 06:27:37

回答

4

您試圖傳遞一個函數作爲回調函數(稍後會調用),但您傳遞的是立即調用函數而不是

你需要編寫調用是這樣的:

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

...這並不奇怪。內部回調是一個函數;外部回調也必須是一個函數。

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

我會建議使用jQuery的承諾特徵,而不是深嵌套。

因此,您將從ajax_fetch函數中返回呼叫的jqXHR。由於它實現了Promise接口,因此您可以撥打.then並在then -callback處撥打下一個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"); 
    }); 
}); 
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); 
}); 

兩個事件處理程序是如此的相似,你可以將它們結合起來。你只需要一個機制來管理不同,它們是:

  • 傳遞給ajax_fetch部分路徑()爲url
  • 警告消息。

首先,爲每個可點擊元素設置一些數據。

$("#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); 
}); 
+0

thanx漫遊者。實際上我正在清理這個問題,這導致我試圖結合一些東西,擺脫一堆冗餘和低效的代碼。我很欣賞這些建議。 – 2015-03-15 06:31:36