2012-11-30 31 views
16

Với những chức năng:Làm cách nào để chuỗi chuỗi các hàm bị trì hoãn trong jQuery 1.8.x?

function func1() { 
    var dfd = $.Deferred(); 

    setTimeout(function() { 
    dfd.resolve('Password'); 
    }, 1000); 

    return dfd.promise(); 
} 

function func2(message) { 
    var dfd = $.Deferred(); 

    setTimeout(function() { 
    if (message == 'Password') { 
     dfd.resolve('Hello World'); 
    } 
    }, 1000); 

    return dfd.promise(); 
} 

Tôi muốn tìm một cách tốt hơn để làm như sau. Lưu ý điều này đang sử dụng jQuery 1.8.x.

var promise = func1(); 

promise.done(function(message1) { 

    var promise2 = func2(message1); 

    promise2.done(function(message2) { 
    alert(message2); 
    }); 
}); 

Bất kỳ ý tưởng nào? Tôi nghĩ rằng bằng cách sử dụng jQuery #pipe hoặC#then sẽ làm việc nhưng tôi không thể tìm ra nó. Đây là một câu đố để chơi xung quanh: http://jsfiddle.net/Z7prn/

Trả lời

34

Nó không phức tạp (hoặc sử dụng .then hoặc .pipe, chúng đều giống nhau kể từ jQuery 1.8 tôi nghĩ).

promise.then(func2).done(function(message) { 
    alert(message); 
}); 

Kể từ func2 trả về một đối tượng thu nhập hoãn lại mới, gọi lại .done được gắn vào một trong những thay thế.

DEMO

+1

tôi yêu khi người ta giải thích điều theo cách ngắn gọn như vậy. dễ hiểu hơn và theo dõi – tim

+1

Lưu ý: Sử dụng '.then' vì' .pipe' đã không được chấp nhận trong jQuery 1.8 ([docs] (http://api.jquery.com/deferred.pipe/)) – nhylated

-2

Sử dụng JQuery.when(). Đó là chính xác những gì bạn muốn chuỗi một chuỗi các trì hoãn và chạy một hàm khi tất cả được thực hiện.

Update 2017 (sau khi nhìn thấy downvotes):

OP gì muốn là một phiên bản tốt hơn của mã của mình để chạy những lời hứa tuần tự. Đây là phiên bản của tôi sử dụng $.when:

function func1() { 
 
    var dfd = $.Deferred(); 
 

 
    setTimeout(function() { 
 
    dfd.resolve('Password'); 
 
    }, 1000); 
 

 
    return dfd.promise(); 
 
} 
 

 
function func2(message) { 
 
    var dfd = $.Deferred(); 
 

 
    setTimeout(function() { 
 
    if (message == 'Password') { 
 
     dfd.resolve('Hello World'); 
 
    } 
 
    }, 1000); 
 

 
    return dfd.promise(); 
 
} 
 

 
// ~~~~~~~~~~ using $.when here ~~~~~~~~~~~~ 
 

 
$.when(func1()).then(function(result1) { 
 
    $.when(func2(result1)).then(function(result2) { 
 
     alert(result2); 
 
    }) 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>

+5

Chúng không chuỗi - chúng được thu thập. Các mảng của các bộ đếm được kích hoạt 'cùng một lúc', và calllback khi() được kích hoạt với tất cả được thực hiện. sau đó(), mặt khác, có thể bị xâu chuỗi để func1() phải được giải quyết trước func2(), v.v. –

+0

@DesignbyAdrian Tại sao bạn giải thích câu hỏi của OP khác? Bạn có thể chạy mã đã đăng của mình hoặc đọc tiêu đề và xem anh * muốn * gửi _chain_ chúng. Anh ấy chỉ đang tìm cách viết lại lần thứ hai bằng cách sử dụng một cách tốt hơn và đó là những gì tôi đã đề cập và chỉ cần thêm một ví dụ. Đầu ra của đoạn trích của tôi giống như của anh ấy (như anh ấy muốn) trong 3 LOC. – Aidin

5

Tôi đã có một trường hợp sử dụng tương tự, vì vậy tôi nghĩ rằng điều này sẽ giúp bạn ra ngoài.

Phương pháp sau sẽ lấy một loạt các phương thức (có thể hoặc không trả lại lời hứa) và thực thi chúng theo thứ tự, đợi cho đến khi mỗi lần trì hoãn hoàn tất trước khi tiếp tục. Hành vi mặc định là dừng lại trên thất bại; đối số thứ hai cho phép bạn tiến hành cuộc gọi không thành công hay không.

thực hiện/không chữ ký handler là (Mảng < bối cảnh>) Chức năng (Mảng < Object {từ chối | giải quyết: luận}>), nơi bối cảnh là bối cảnh của mỗi resolveWith cuộc gọi/rejectWith, hoặc trì hoãn được đề cập và đối số là bộ đối số được chuyển trong độ phân giải/từ chối.

(function ($) { 
    "use strict"; 
    var copy = function (a) { 
     return Array.prototype.slice.call(a); 
    }; 

    /** 
     Handle a sequence of methods, stopping on failure by default 
     @param Array<Function> chain List of methods to execute. Non-deferred return values will be treated as successful deferreds. 
     @param Boolean continueOnFailure Continue executing even if one of the returned deferreds fails. 
     @returns Deferred 
    */ 
    $.sequence = function (chain, continueOnFailure) { 
     var handleStep, handleResult, 
      steps = copy(chain), 
      def = new $.Deferred(), 
      defs = [], 
      results = []; 
     handleStep = function() { 
      if (!steps.length) { 
       def.resolveWith(defs, [ results ]); 
       return; 
      } 
      var step = steps.shift(), 
       result = step(); 
      handleResult(
       $.when(result).always(function() { 
        defs.push(this); 
       }).done(function() { 
        results.push({ resolved: copy(arguments) }); 
       }).fail(function() { 
        results.push({ rejected: copy(arguments) }); 
       }) 
      ); 
     }; 
     handleResult = continueOnFailure ? 
       function (result) { 
        result.always(function() { 
         handleStep(); 
        }); 
       } : 
       function (result) { 
        result.done(handleStep) 
         .fail(function() { 
          def.rejectWith(defs, [ results ]); 
         }); 
       }; 
     handleStep(); 
     return def.promise(); 
    }; 
}(this.jQuery)); 

Một ví dụ đơn giản sử dụng: http://jsfiddle.net/rG9rA/

function func1() { 
    var dfd = $.Deferred(); 

    setTimeout(function() { 
    dfd.resolve('Password'); 
    }, 1000); 

    return dfd.promise(); 
} 

function func2(message) { 
    var dfd = $.Deferred(); 

    setTimeout(function() { 
    if (message == 'Password') { 
     dfd.resolve('Hello World'); 
    } 
    }, 1000); 

    return dfd.promise(); 
} 

    $.sequence([func1, func2, function() { alert('done'); }]); 
+0

Rất đẹp. Tôi đã thêm một "chậm trễ" tùy chọn giữa các cuộc gọi, trong trường hợp một số mã bên ngoài cần sự kiện để giải quyết (tôi sử dụng Knockout) –

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