2012-07-12 32 views
14

Làm cách nào để sử dụng đúng cách jQuery trì hoãn trả về hàm cho đến khi cuộc gọi không đồng bộ trong hàm hoàn thành + nhận giá trị trả về?jQuery hoãn lại: sử dụng để trì hoãn trả về hàm cho đến khi cuộc gọi không đồng bộ trong hàm hoàn thành + nhận giá trị trả lại

Đây là mã hiện tại của tôi:

function getFields(page) 
{ 
    var dff = $.Deferred(); 
    result = {}; 
    $.ajax(//the async call 
    { 
     url: page, 
     success: 
     function (data) 
     { 
      //work out values for field1 & field 2 from data here 
      result = 
      { 
      'field1' : field1, 
      'field2' : field2 
      }; 
     }, 
     complete: 
     function() 
     { 
      dff.resolve(result); //my attempt to return the result 
     } 
    } 
); 
    return dff.promise(); 
} 

Tôi muốn này để in { "field1": "value1", "field2": "value2"}

var result = getFields('http://something'); 
console.log(JSON.stringify(result)); 

Tuy nhiên, giá trị kết quả dường như là một đối tượng jQuery - vì vậy tôi đang làm điều gì sai, nhưng cái gì?

Cảm ơn!


P.S. Xin lỗi cho câu hỏi newbie, tôi là người dùng lần đầu tiên bị trì hoãn, vì vậy tôi vẫn đang nắm bắt các khái niệm cơ bản.

Trả lời

12

Cách duy nhất để trì hoãn sự trở lại của chức năng getFields của bạn sẽ được thiết lập thuộc tính AJAX async false:

var ajaxPromise = $.ajax(
    { 
     url: page, 
     async: false // make the call synchronous 
    } 
); 

Nhưng các tài liệu jQuery lưu ý rằng điều này bị phản đối từ 1,8 trở lên (tức là nó sử dụng là nản lòng).

Trì hoãn không đồng bộ hóa AJAX, thay vào đó chúng giúp dễ dàng hơn khi làm việc với các cuộc gọi lại và các phương thức không đồng bộ.

Từ những gì tôi có thể nói về những gì bạn đang cố gắng để nó có thể làm việc tốt hơn để làm điều gì đó như thế này:

function getFields(page) 
{ 
    var ajaxPromise = $.ajax(//the async call 
    { 
     url: page 
    } 
); 

    var dff = $.Deferred(); 
    ajaxPromise.then(function(data){ 

    // Possibly access the loaded data in this function. 
    var result = { 
     'field1' : field1, 
     'field2' : field2 
    }; 

    // Notify listeners that the AJAX call completed successfully. 
    dff.resolve(result); 

    }, function(){ 
    // Something went wrong - notify listeners: 
    dff.reject(/* possibly pass information about the error */); 
    }); 

    return dff.promise(); 
} 

Sau đó, sử dụng đối tượng hứa hẹn như thế này:

var fieldPromise = getFields('http://something'); 
fieldPromise.done(function(result){ 
    console.log(JSON.stringify(result)); 
}); 

Lưu ý rằng getFields trả về một đối tượng Promise ngay lập tức nhưng bạn phải chờ lời hứa được giải quyết trước khi bạn có thể đăng xuất kết quả.

+0

@ Sly_caridnal: +1 và kiểm tra - giải thích tuyệt vời! – bguiz

+0

Oooh, đẹp ... Gói 'dff.resolve (dữ liệu);' trong một 'setTimeout' là một cách nhanh chóng và dễ dàng để mô phỏng một cuộc gọi ajax chậm (vì những gì tôi đang thử nghiệm không nhất quán kết thúc trước hoặc sau một cuộc gọi ajax thứ hai) – Izkata

+0

Có một cách thực sự: thay đổi câu lệnh trả về của hàm getFields (trang) 'như' return dff.promise(). getState() == 'resolve'' Nó sẽ tạm dừng cho đến khi giải quyết hoặc từ chối xảy ra. Tất nhiên bạn chỉ có thể trả lại đối tượng lời hứa và kiểm tra trạng thái ở một nơi khác. – shuangwhywhy

6

Đây là ý tưởng cơ bản về trì hoãn: bạn được trả về một đối tượng và bạn có thể sử dụng nó để xác định các hàm sẽ được gọi khi giá trị trả về quay lại. Vì vậy, bạn có thể làm điều gì đó như:

function getFields(page) 
{ 
    return $.ajax(page); 
} 

Sau đó, bạn có thể gọi nó và chỉ định một hàm được gọi khi cuộc gọi XHR hoàn thành:

var jqXHR = getFields("/path/to/call"); 
jqXHR.done(function (data) { alert(JSON.stringify(data); }); 

Đối tượng là thể kết nối, vì vậy bạn chỉ có thể làm được điều này :

getFields("/path/to/call") 
    .done(function (data) { alert(JSON.stringify(data); }); 

Lưu ý rằng đối tượng jqXHR trả về bởi $.ajax là một thu nhập hoãn lại tương thích với đối tượng, vì vậy bạn có thể đọc tài liệu tại http://api.jquery.com/category/deferred-object/.

Tôi không chắc chắn những gì bạn có nghĩa là bởi mẫu mã của bạn (vì nó không thực sự sử dụng các cuộc gọi Ajax) nhưng có lẽ bạn có nghĩa là một cái gì đó như thế này:

function getFields() 
{ 
    var df = $.Deferred(); 
    window.setTimeout(function() { 
     df.resolve({field1: "value1", field2: "value2"}); 
    }, 1000); 
    return df.promise(); 
} 

getFields().done(function (data) { console.log(JSON.stringify(data)); }); 

này sẽ in giá trị mong muốn của bạn một thứ hai sau khi bạn chạy nó.

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