2011-01-25 25 views
54

Có thể vấn đề như vậy không phải là mới, nhưng tôi không tìm thấy bất cứ điều gì tương tự. Tôi có mã jQuery như:

$.ajax({ 
    url : ('/people/'+id), 
    type : 'DELETE', 
    dataType : 'json', 
    success : function(e) { 
    table.getItems(currentPage); 
    } 
}); 

Rails My điều khiển trông như thế này:

def destroy 
    @person = Person.find(params[:id]) 
    @person.destroy 

    respond_to do |format| 
     format.html { redirect_to(people_url) } 
     format.json { render :json => @person, :status => :ok } 
    end 
end 

này đang làm việc.

Nhưng khi tôi sử dụng sau (như được tạo ra bởi tiêu chuẩn), gọi lại success không được gọi là:

def destroy 
    @person = Person.find(params[:id]) 
    @person.destroy 

    respond_to do |format| 
     format.html { redirect_to(people_url) } 
     format.json { head :ok } 
    end 
end 

Tested dưới rails 3.0.3, jQuery 1.4.2Firefox 3.6.13.
Firebug cho biết, truy vấn đó được kích hoạt và trả về 200 OK trong cả hai trường hợp, mục cũng sẽ bị xóa trong cả hai trường hợp. Nhưng trong trường hợp thứ hai gọi lại không được gọi.

Có sự khác biệt đáng kể trong REST và có cách nào để sử dụng jQuery bằng cách sử dụng bộ điều khiển giàn giáo không?

+0

Cả hai yêu cầu đều trả về JSON hợp lệ không? Bạn có thể sniff với Charles hoặc nhấn chúng bằng tay với curl và xem những gì trở lại? –

+0

có một trích dẫn bị thiếu trong url của bạn, .. chỉ trong trường hợp. – jAndy

+0

thiếu qoute xuất hiện khi tôi chuẩn bị mã cho một câu hỏi :) – sandrew

Trả lời

70

Tôi đã chạy qua một vài lần và câu trả lời rất đơn giản.

Bạn đang sử dụng dataType : 'json' trong cuộc gọi $ .ajax của mình, vì vậy jQuery đang mong đợi phản hồi JSON. Với head :ok Đường ray trả về phản hồi có chứa một dấu cách (http://github.com/rails/rails/issues/1742), không được jQuery chấp nhận làm JSON hợp lệ. Vì vậy, nếu bạn thực sự mong đợi để có được một lỗi hoặc một tiêu đề 200 OK OK, chỉ cần đặt dataType : 'html' trong yêu cầu của bạn và nó sẽ hoạt động (nếu bạn không đặt dataType, jQuery sẽ cố gắng đoán loại dựa trên các tiêu đề phản hồi, v.v. và vẫn có thể đoán được json, trong trường hợp này bạn vẫn gặp vấn đề này). Nếu bạn thực sự mong muốn lấy lại JSON, thay vì sử dụng head :ok hãy hiển thị nội dung nào đó hợp lệ với JSON (xem nhận xét) hoặc chỉ sử dụng head :no_content theo đề xuất của @Waseem

+1

bạn sẽ làm gì để trả lại lỗi trong trường hợp này? – lulalala

+1

head: internal_server_error hoặc render: status => 500 – Duke

+2

Cách tốt hơn là sử dụng 'head: no_content'. Xem http://stackoverflow.com/a/12751298/100466 và https://github.com/rails/rails/issues/1742 – Waseem

0

Điều này đôi khi được gây ra bởi phiên bản cũ của Plugin xác thực jQuery. Nếu bạn đang sử dụng plugin này, điều này đôi khi dẫn đến vấn đề này. Có bản cập nhật sửa lỗi này, nếu nó áp dụng cho trường hợp của bạn.

Ngoài ra, bạn có lẽ có thể tìm ra những gì đang xảy ra sai bằng cách thiết lập một trình xử lý lỗi qua:

$.ajaxSetup() hoặc $.ajaxError()

Điều này có lẽ sẽ trả về một lỗi phân tích cú pháp. Các phiên bản mới hơn của jQuery nổi tiếng là rất nghiêm ngặt liên quan đến phân tích cú pháp JSON.

+0

không, tôi không sử dụng bất kỳ plugin jQuery nào (ngoại trừ một số plugin tôi đã viết bản thân mình, nhưng họ không có ảnh hưởng đến ajax). Và tôi biết, rằng trong trường hợp máy chủ mô tả trả về câu trả lời trống, và jquery, có lẽ, không thể phân tích nó. Và tôi muốn biết nếu có một cách khá hay để làm cho nó hoạt động với câu trả lời _empty_ này. – sandrew

+0

Tôi giả định rằng bất kỳ điều gì không phân tích cú pháp, bao gồm cả câu trả lời trống sẽ kích hoạt cuộc gọi lại ajaxError, vì vậy bạn có thể thiết lập trình xử lý cho nó ở đó. –

6

GearHead là chính xác, ngoại trừ trình phân tích cú pháp jQuery thực sự đủ thông minh xử lý một đáp ứng chuỗi trống rỗng và không cố gắng phân tích cú pháp nó.

Tuy nhiên nếu bạn có các cuộc gọi mà đôi khi sẽ nhận json và đôi khi nhận được phản hồi head, và bạn không có quyền truy cập vào máy chủ hoặc không muốn thay đổi tất cả head cuộc gọi của bạn, bạn có thể làm giải pháp thay thế này:

vấn đề là Rails sẽ gửi một không gian duy nhất như là một phản hồi trống khi bạn sử dụng head (xem ở đây: How to return truly empty body in rails? i.e. content-length 0)

các bộ phận có liên quan của hàm nhìn jQuery parseJSON như thế này tại thời điểm viết bài này:

parseJSON: function(data) { 
    if (typeof data !== "string" || !data) { 
     return null; 
    } 

    // Make sure leading/trailing whitespace is removed (IE can't handle it) 
    data = jQuery.trim(data); 

    // Attempt to parse using the native JSON parser first 
    if (window.JSON && window.JSON.parse) { 
     return window.JSON.parse(data); 
    } 

Như bạn có thể thấy, jQuery đang kiểm tra xem dữ liệu có phải là một chuỗi rỗng trước khi cắt xén hay không. Sau đó nó cố gắng để JSON.parse("") mà bạn có thể thấy trong bảng điều khiển của bạn dẫn đến lỗi, kích hoạt gọi lại lỗi ajax qua câu lệnh catch.

Có một cách khắc phục đơn giản. jQuery cho phép bạn sử dụng các trình biến đổi khi một kiểu dữ liệu được yêu cầu và một kiểu dữ liệu khác được trả về. Xem tại đây để biết thêm chi tiết: http://api.jquery.com/extending-ajax/

Do đường ray head phản hồi hiển thị dưới dạng văn bản, bạn có thể chỉ cần xác định văn bản thành công cụ chuyển đổi json sẽ cắt phản ứng trước khi cố gắng phân tích cú pháp. Chỉ cần thêm đoạn mã này:

// deal with rails ' ' empty response 
jQuery.ajaxSetup({ 
    converters: { 
    "text json": function (response) { 
     jQuery.parseJSON($.trim(response)) 
    } 
    } 
}) 
+0

FYI, 'jQuery.parseJSON' chỉ là một [passthrough đến' JSON.parse'] (https://github.com/jquery/jquery/blob/master/src/ajax/parseJSON.js), mà ném một ngoại lệ trên một chuỗi rỗng ("kết thúc đầu vào bất ngờ"). Vì vậy, điều này nên kiểm tra một cách rõ ràng cho đáp ứng trống ('$ .trim (response) .length == 0') và' return null'. – nornagon

Các vấn đề liên quan