2016-03-08 18 views
11

Tôi đang cố gắng hiểu API lời hứa và chuỗi, đặc biệt là thời điểm khi $timeout được sử dụng với .then(). Những gì tôi đã mong đợi từ sau đây là kể từ khi $timeout trả về một lời hứa, .then() sẽ không được gọi cho đến khi nó đã được giải quyết.

Nhưng thay vì ABAB, đó là ABBA mọi lúc.

Làm cách nào để sử dụng API lời hứa để đảm bảo cuộc gọi chạy dài (hoặc cuộc gọi bị trì hoãn sử dụng $timeout) thực sự hoàn tất trước khi .then() được thực thi?

angular 
    .module('app', []) 
    .controller('ThenCtrl', ThenCtrl); 

function ThenCtrl($timeout, $q) { 
    var vm = this; 

    vm.items = []; 

    $q.when(pushA()).then(pushB()); 

    $timeout(pushA, 5000).then(pushB()); 

    function pushA() { 
    vm.items.push('A'); 
    } 

    function pushB() { 
    vm.items.push('B'); 
    } 
} 

Markup

<div ng-app="app"> 
    <div ng-controller="ThenCtrl as vm"> 
    {{vm.items}} 
    </div> 
</div> 

tôi đã thiết lập một fiddle: https://jsfiddle.net/kan3c61t/

Trả lời

13

Đừng gọi các chức năng bên trong .then phương pháp.

$q.when(pushA()).then(pushB); 
    //$q.when(pushA()).then(pushB()); 

    $timeout(pushA, 5000).then(pushB); 
    //$timeout(pushA, 5000).then(pushB()); 

Thay vào đó, hãy chuyển các hàm làm đối số cho phương thức .then. Dịch vụ $q sẽ giữ các chức năng này được gọi sau.

Cách hoạt động của dịch vụ $q là lưu trữ đối số của phương thức .then làm hàm để gọi sau. Trong trường hợp này, dịch vụ $q đã lưu trữ giá trị trả về pushB() với tác dụng phụ của việc đẩy B ngay lập tức lên mảng.

Các DEMO on JSFiddle

+0

Đây là một giải pháp khá thú vị. –

+2

Rất rõ ràng. Sự khác biệt mà các cặp cha mẹ có thể tạo ra. – twip

+0

Điều này đã giúp tôi rất nhiều – Fergus

6

Ở đây bạn đi. Những gì tôi đã làm về cơ bản được thêm một hàm success trong phần then của mã.

$timeout(pushA, 5000).then(function(success) { 
    pushB() 
    }); 

Đây là thao tác demo.

Bạn cũng có thể thêm một error function như thế này

$timeout(pushA, 5000).then(function(success) { 
    pushB() 
    },function(error){console.log("Error");}); 

Trong khi tìm kiếm câu trả lời này, tôi cũng đã xem qua này rất helpful link

+1

Đây là lời nhắc tuyệt vời về cấu trúc API cơ bản; cảm ơn bạn. – twip

4

Như những người khác đã đề cập - vấn đề lớn hơn của bạn là bạn .then(promise) và không .then(function).

Lời hứa thể hiện giá trị + thời gian. Đó là kết quả của một hoạt động đã bắt đầu. Lời hứa là giá trị - then chờ cho các chức năng . Bạn không thể "chạy lời hứa sau lời hứa khác" - vì lời hứa có nghĩa là hoạt động đã bắt đầu.

Khi bạn then(x) cho bất kỳ điều gì khác ngoài chức năng thì bị bỏ qua.Đây là một sự lựa chọn không may trong spec hứa hẹn nhưng chúng ta phải sống với nó.

Vì cuộc gọi của bạn đồng bộ, bạn không nên sử dụng lời hứa cho nó. Nếu mã của bạn làm điều gì đó đồng bộ bạn có thể lập trình tự hành động với ; và không then:

pushA(); 
pushB(); 

Nếu đó là một cuộc gọi mà trả lời hứa sau đó nó chỉ trở thành:

pushA().then(pushB); 

Không có điểm trong việc kêu gọi $q.when mà chuyển đổi những lời hứa không hứa hẹn.

Tôi muốn viết nó như:

pushA(); 
$timeout(5000).then(pushB); 

Không có điểm để chuyển đổi các hành động đồng bộ đầu tiên một hàm trả về lời hứa hoặc liên quan đến những lời hứa bất cứ nơi nào ngoại trừ thời gian chờ. Nếu bạn cần pushA xảy ra sau khi 5000ms bản thân tôi vẫn có thể viết:

$timeout(5000).then(pushA).then(pushB) 

Vì tôi nghĩ rằng đó là dễ đọc hơn và một lần nữa chúng tôi không liên quan đến pushApushB với lời hứa trực tiếp.

+0

Cảm ơn bạn đã phản hồi. Đôi khi rất khó để nắm bắt ý định tốt trong khi vừa ngắn gọn vừa rõ ràng cho các bài đăng SO. Những gì tôi đã cố gắng để nắm bắt là một kịch bản mà chúng tôi dự định A được giải quyết trước B, và A là lời hứa phải thực hiện sự chậm trễ. Có nghĩa là: Tôi muốn 'pushA' hoàn thành công việc của nó, bao gồm cả sự chậm trễ, và sau đó-và-chỉ-sau đó thực thi' pushB'. Dưới đây là một fiddle cập nhật, được thực hiện với đầu vào của bạn, giúp tôi đến những gì tôi đang tìm kiếm: https://jsfiddle.net/nam3cbaw/1/ – twip

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