Sự khác biệt giữa Trì hoãn, Hứa hẹn và Tương lai là gì?
Có một lý thuyết thường được phê duyệt đằng sau cả ba?
Sự khác biệt giữa Trì hoãn, Hứa hẹn và Tương lai là gì?
Có một lý thuyết thường được phê duyệt đằng sau cả ba?
Câu trả lời:
Trước sự không thích rõ ràng về cách tôi đã cố gắng trả lời câu hỏi của OP. Câu trả lời theo nghĩa đen là, một lời hứa là một cái gì đó được chia sẻ với các đối tượng khác, trong khi hoãn lại nên được giữ kín. Chủ yếu, một lời nói bị trì hoãn (thường kéo dài Promise) có thể tự giải quyết, trong khi một lời hứa có thể không thể thực hiện được.
Nếu bạn quan tâm đến các chi tiết vụn vặt, hãy xem Promise / A + .
Theo như tôi biết, mục đích bao trùm là cải thiện sự rõ ràng và nới lỏng khớp nối thông qua một giao diện được tiêu chuẩn hóa. Xem gợi ý đọc từ @ jfriend00:
Thay vì trực tiếp chuyển các cuộc gọi lại đến các chức năng, một cái gì đó có thể dẫn đến các giao diện được kết nối chặt chẽ, sử dụng các lời hứa cho phép người ta tách các mối quan tâm về mã đồng bộ hoặc không đồng bộ.
Cá nhân, tôi thấy việc trì hoãn đặc biệt hữu ích khi xử lý các ví dụ được tạo bởi các yêu cầu không đồng bộ, tải tập lệnh có mạng phụ thuộc và cung cấp phản hồi của người dùng để tạo dữ liệu theo cách không chặn.
Thật vậy, hãy so sánh hình thức gọi lại thuần túy để làm một cái gì đó sau khi tải CodeMirror ở chế độ JS không đồng bộ (xin lỗi, tôi đã không sử dụng jQuery trong một thời gian ):
/* assume getScript has signature like: function (path, callback, context)
and listens to onload && onreadystatechange */
$(function () {
getScript('path/to/CodeMirror', getJSMode);
// onreadystate is not reliable for callback args.
function getJSMode() {
getScript('path/to/CodeMirror/mode/javascript/javascript.js',
ourAwesomeScript);
};
function ourAwesomeScript() {
console.log("CodeMirror is awesome, but I'm too impatient.");
};
});
Đối với phiên bản được hứa hẹn (một lần nữa, xin lỗi, tôi không cập nhật trên jQuery):
/* Assume getScript returns a promise object */
$(function () {
$.when(
getScript('path/to/CodeMirror'),
getScript('path/to/CodeMirror/mode/javascript/javascript.js')
).then(function () {
console.log("CodeMirror is awesome, but I'm too impatient.");
});
});
Xin lỗi về mã bán giả, nhưng tôi hy vọng nó làm cho ý tưởng cốt lõi phần nào rõ ràng. Về cơ bản, bằng cách trả lại một lời hứa được tiêu chuẩn hóa, bạn có thể vượt qua lời hứa xung quanh, do đó cho phép phân nhóm rõ ràng hơn.
fn(callback, errback)
là không có bất kỳ kết hợp chặt chẽ hoặc ít hữu ích hơn fn().then(callback, errback)
- nhưng dù sao đó là một cách sai để sử dụng lời hứa. Tôi đặc biệt ghét $.when
ví dụ sùng bái hàng hóa - hoàn toàn không có lý do gì bạn không thể có $.when
chức năng làm việc với các cuộc gọi lại.
Những câu trả lời này, bao gồm câu trả lời được chọn, rất tốt để đưa ra những lời hứa về mặt khái niệm, nhưng thiếu chi tiết cụ thể về sự khác biệt chính xác trong thuật ngữ phát sinh khi sử dụng các thư viện thực hiện chúng (và có những khác biệt quan trọng).
Vì nó vẫn là một thông số kỹ thuật đang phát triển , câu trả lời hiện tại đến từ việc cố gắng khảo sát cả các tài liệu tham khảo (như wikipedia ) và triển khai (như jQuery ):
Trì hoãn : Không bao giờ được mô tả trong các tài liệu tham khảo phổ biến,
1 2 3 4
nhưng thường được sử dụng bởi các triển khai như là trọng tài giải quyết lời hứa (thực hiện và ).
5 6 7
resolve
reject
Đôi khi, việc trì hoãn cũng là những lời hứa (thực hiện then
),
5 6
lần khác, nó được coi là thuần túy hơn khi chỉ có khả năng giải quyết và buộc người dùng truy cập vào lời hứa để sử dụng .
7
then
Promise : Từ bao quát nhất cho chiến lược đang thảo luận.
Một đối tượng proxy lưu trữ kết quả của một hàm mục tiêu có tính đồng bộ mà chúng tôi muốn trừu tượng hóa, cộng với việc phơi bày một then
hàm chấp nhận một hàm mục tiêu khác và trả lại một lời hứa mới.
2
Ví dụ từ CommonJS :
> asyncComputeTheAnswerToEverything()
.then(addTwo)
.then(printResult);
44
Luôn được mô tả trong các tài liệu tham khảo phổ biến, mặc dù không bao giờ quy định trách nhiệm giải quyết trách nhiệm của ai. 1 2 3 4
Luôn luôn có mặt trong các triển khai phổ biến, và không bao giờ đưa ra khả năng giải quyết. 5 6 7
Tương lai : một thuật ngữ dường như không được dùng trong một số tài liệu tham khảo phổ biến 1 và ít nhất một triển khai phổ biến, 8 nhưng dường như bị loại bỏ khỏi cuộc thảo luận để ưu tiên cho thuật ngữ 'lời hứa' 3 và không phải lúc nào cũng được đề cập trong phần giới thiệu phổ biến cho chủ đề này. 9
Tuy nhiên, ít nhất một thư viện sử dụng thuật ngữ chung để trừu tượng hóa tính đồng bộ và xử lý lỗi, trong khi không cung cấp then
chức năng.
10
Không rõ ràng nếu tránh thuật ngữ 'lời hứa' là có chủ ý, nhưng có lẽ là một lựa chọn tốt vì các lời hứa được xây dựng xung quanh 'các mục tiêu'.
2
Sự khác biệt giữa Lời hứa / A và Lời hứa / A +
(TL; DR, Lời hứa / A + chủ yếu giải quyết sự mơ hồ trong Lời hứa / A)
Task
Điều thực sự khiến tất cả nhấp vào tôi là bài thuyết trình này của Domenic Denicola.
Trong một ý chính , anh ấy đã đưa ra mô tả mà tôi thích nhất, nó rất súc tích:
Điểm hứa hẹn là cung cấp cho chúng tôi trở lại thành phần chức năng và lỗi bong bóng trong thế giới không đồng bộ.
Nói cách khác, lời hứa là một cách cho phép chúng ta viết mã không đồng bộ gần như dễ viết như thể nó là đồng bộ .
Xem xét ví dụ này, với những lời hứa:
getTweetsFor("domenic") // promise-returning async function
.then(function (tweets) {
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
return expandUrlUsingTwitterApi(mostRecentShortUrl); // promise-returning async function
})
.then(doHttpRequest) // promise-returning async function
.then(
function (responseBody) {
console.log("Most recent link text:", responseBody);
},
function (error) {
console.error("Error with the twitterverse:", error);
}
);
Nó hoạt động như thể bạn đang viết mã đồng bộ này:
try {
var tweets = getTweetsFor("domenic"); // blocking
var shortUrls = parseTweetsForUrls(tweets);
var mostRecentShortUrl = shortUrls[0];
var responseBody = doHttpRequest(expandUrlUsingTwitterApi(mostRecentShortUrl)); // blocking x 2
console.log("Most recent link text:", responseBody);
} catch (error) {
console.error("Error with the twitterverse: ", error);
}
(Nếu điều này vẫn có vẻ phức tạp, hãy xem bản trình bày đó!)
Về Trì hoãn, đó là một cách để .resolve()
hoặc .reject()
lời hứa. Trong thông số Promising / B , nó được gọi .defer()
. Trong jQuery, nó $.Deferred()
.
Xin lưu ý rằng, theo như tôi biết, việc triển khai Promise trong jQuery bị hỏng (xem ý chính đó), ít nhất là với jQuery 1.8.2.
Nó được cho là thực hiện Promise / A thenables , nhưng bạn không nhận được cách xử lý lỗi chính xác, theo nghĩa là toàn bộ chức năng "async try / Catch" sẽ không hoạt động. Thật đáng tiếc, bởi vì việc "thử / bắt" với mã async hoàn toàn tuyệt vời.
Nếu bạn định sử dụng Promise (bạn nên dùng thử với mã của riêng bạn!), Hãy sử dụng Q của Kris Kowal . Phiên bản jQuery chỉ là một số trình tổng hợp gọi lại để viết mã jQuery sạch hơn, nhưng bỏ lỡ điểm.
Về Tương lai, tôi không biết, tôi chưa thấy điều đó trong bất kỳ API nào.
Chỉnh sửa: Cuộc trò chuyện trên youtube của Domenic Denicola về Lời hứa từ bình luận của @Farm bên dưới.
Một trích dẫn của Michael Jackson (vâng, Michael Jackson ) từ video:
Tôi muốn bạn ghi cụm từ này trong tâm trí của bạn: Một lời hứa là một giá trị không đồng bộ .
Đây là một mô tả xuất sắc: một lời hứa giống như một biến số từ tương lai - một tham chiếu hạng nhất đến một cái gì đó, tại một thời điểm nào đó, sẽ tồn tại (hoặc xảy ra).
Một Promise đại diện cho một proxy cho một giá trị không nhất thiết phải biết đến khi sự hứa hẹn được tạo ra. Nó cho phép bạn liên kết các trình xử lý với giá trị thành công cuối cùng của hành động không đồng bộ hoặc lý do thất bại. Điều này cho phép các phương thức không đồng bộ trả về các giá trị như các phương thức đồng bộ: thay vì giá trị cuối cùng, phương thức không đồng bộ trả về một lời hứa sẽ có giá trị tại một thời điểm nào đó trong tương lai.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Các deferred.promise()
phương pháp cho phép một chức năng không đồng bộ để ngăn chặn mã khác can thiệp vào tiến độ hoặc trạng thái của yêu cầu nội bộ của mình. Promise chỉ hiển thị các phương thức Trì hoãn cần thiết để đính kèm các trình xử lý bổ sung hoặc xác định trạng thái ( sau đó, thực hiện, thất bại, luôn luôn, đường ống, tiến trình, trạng thái và lời hứa ), nhưng không phải là các phương thức thay đổi trạng thái ( giải quyết, từ chối, thông báo, giải quyết, từ chối với, và thông báo với ).
Nếu mục tiêu được cung cấp, deferred.promise()
sẽ đính kèm các phương thức vào nó và sau đó trả về đối tượng này thay vì tạo một đối tượng mới. Điều này có thể hữu ích để đính kèm hành vi Promise với một đối tượng đã tồn tại.
Nếu bạn đang tạo Trì hoãn, hãy giữ một tham chiếu đến Trì hoãn để có thể giải quyết hoặc từ chối tại một số điểm. Chỉ trả về đối tượng Promise thông qua deferred.promise () để mã khác có thể đăng ký gọi lại hoặc kiểm tra trạng thái hiện tại.
Đơn giản là chúng ta có thể nói rằng một Promise đại diện cho một giá trị chưa được biết đến như là một Trì hoãn đại diện cho công việc chưa hoàn thành.
promise
đại diện cho một giá trị chưa được biết đến deferred
tác phẩm đại diện chưa hoàn thànhMột lời hứa là một giữ chỗ cho một kết quả ban đầu không xác định trong khi hoãn lại đại diện cho tính toán dẫn đến giá trị.
Tài liệu tham khảo