Rõ ràng thông qua
Tương tự như lồng các hàm gọi lại, kỹ thuật này dựa vào các bao đóng. Tuy nhiên, chuỗi vẫn không thay đổi - thay vì chỉ chuyển kết quả mới nhất, một số đối tượng trạng thái được truyền cho mỗi bước. Các đối tượng trạng thái này tích lũy kết quả của các hành động trước đó, bàn giao tất cả các giá trị sẽ cần sau này cộng với kết quả của nhiệm vụ hiện tại.
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return promiseB(…).then(b => [resultA, b]); // function(b) { return [resultA, b] }
}).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
Ở đây, mũi tên nhỏ đó b => [resultA, b]
là hàm đóng lại resultA
và chuyển một mảng của cả hai kết quả sang bước tiếp theo. Mà sử dụng cú pháp hủy tham số để phá vỡ nó trong các biến đơn.
Trước khi phá hủy đã có sẵn với ES6, một phương thức trợ giúp tiện lợi được gọi là .spread()
được cung cấp bởi nhiều thư viện hứa hẹn ( Q , Bluebird , khi , đấm ). Nó nhận một hàm có nhiều tham số - một tham số cho mỗi phần tử mảng - sẽ được sử dụng như .spread(function(resultA, resultB) { …
.
Tất nhiên, việc đóng cửa cần thiết ở đây có thể được đơn giản hóa hơn nữa bởi một số chức năng của trình trợ giúp, ví dụ:
function addTo(x) {
// imagine complex `arguments` fiddling or anything that helps usability
// but you get the idea with this simple one:
return res => [x, res];
}
…
return promiseB(…).then(addTo(resultA));
Ngoài ra, bạn có thể sử dụng Promise.all
để tạo lời hứa cho mảng:
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return Promise.all([resultA, promiseB(…)]); // resultA will implicitly be wrapped
// as if passed to Promise.resolve()
}).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
Và bạn có thể không chỉ sử dụng các mảng, mà các đối tượng phức tạp tùy ý. Ví dụ: có _.extend
hoặc Object.assign
trong một hàm trợ giúp khác:
function augment(obj, name) {
return function (res) { var r = Object.assign({}, obj); r[name] = res; return r; };
}
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return promiseB(…).then(augment({resultA}, "resultB"));
}).then(function(obj) {
// more processing
return // something using both obj.resultA and obj.resultB
});
}
Trong khi mô hình này đảm bảo một chuỗi phẳng và các đối tượng trạng thái rõ ràng có thể cải thiện sự rõ ràng, nó sẽ trở nên tẻ nhạt đối với một chuỗi dài. Đặc biệt khi bạn chỉ cần nhà nước lẻ tẻ, bạn vẫn phải vượt qua từng bước. Với giao diện cố định này, các cuộc gọi lại trong chuỗi được kết hợp khá chặt chẽ và không thể thay đổi. Nó làm cho việc thực hiện các bước đơn trở nên khó khăn hơn và các cuộc gọi lại không thể được cung cấp trực tiếp từ các mô-đun khác - chúng luôn cần được bọc trong mã soạn sẵn quan tâm đến trạng thái. Các chức năng trợ giúp trừu tượng như trên có thể làm giảm cơn đau một chút, nhưng nó sẽ luôn hiện diện.
javascript
, nó có liên quan trong ngôn ngữ khác. Tôi chỉ sử dụng câu trả lời "phá vỡ chuỗi" trong java và jdeferred