Hiểu lời hứa trong Node.js


147

Từ những gì tôi đã hiểu, có ba cách gọi mã không đồng bộ:

  1. Sự kiện, ví dụ request.on("event", callback);
  2. Gọi lại, vd fs.open(path, flags, mode, callback);
  3. Hứa

Tôi đã tìm thấy thư viện lời hứa nút nhưng tôi không nhận được.

Ai đó có thể giải thích những gì hứa hẹn là tất cả về và tại sao tôi nên sử dụng nó?

Ngoài ra, tại sao nó bị xóa khỏi Node.js?


Bài viết này giải thích nó khá tốt. Khi nói đến việc triển khai có thể sử dụng được trong node.js, hãy xem Futures
Sean Kinsey

Đây là một chuỗi tuyệt vời tôi đã sử dụng để tạo lớp hứa hẹn của riêng mình: Hãy tạo một Khung: Hứa hẹn Đây là video về jQuery Trì hoãn: blog.bigbinary.com/2011/09/03/jquery-deferred.html
Tom Winter

Câu trả lời:


91

Hứa hẹn trong node.js hứa sẽ thực hiện một số công việc và sau đó có các cuộc gọi lại riêng biệt sẽ được thực hiện để thành công và thất bại cũng như xử lý thời gian chờ. Một cách khác để nghĩ về những lời hứa trong node.js là chúng là các trình phát chỉ có thể phát ra hai sự kiện: thành công và lỗi.

Điều thú vị về lời hứa là bạn có thể kết hợp chúng thành chuỗi phụ thuộc (chỉ thực hiện Promise C khi Promise A Promise B hoàn thành).

Bằng cách loại bỏ chúng khỏi node.js lõi, nó tạo ra khả năng xây dựng các mô-đun với các triển khai khác nhau của các lời hứa có thể nằm trên lõi. Một số trong số này là nút hứa hẹntương lai .


10
@weng Không, không phải vậy.
Ivo Wetzel

98

Vì câu hỏi này vẫn có nhiều quan điểm (như của tôi), tôi muốn chỉ ra rằng:

  1. nút-lời hứa trông khá chết đối với tôi (lần cam kết cuối cùng là khoảng 1 năm trước) và gần như không có bài kiểm tra nào.
  2. các kỳ hạn mô-đun vẻ rất cồng kềnh với tôi và được ghi nhận nặng (và tôi nghĩ rằng các quy ước đặt tên chỉ là xấu)
  3. Cách tốt nhất để đi dường như là khung q , cả hoạt động và tài liệu tốt.

9
Ngoài ra, hãy kiểm tra github.com/medikoo/deferred này , Q là một trong những người đầu tiên và nó chắc chắn là nguồn cảm hứng cho nhiều triển khai xuất hiện sau đó, nhưng thật không may, nó rất chậm và quá "lý thuyết" trong một số phần, nó không chơi tốt với một số phần kịch bản thế giới thực
Mariusz Nowak

Tôi sẽ xem video này theo lời hứa của một trong những người tạo ra RSVP.js youtube.com/,
chạy

23
Cập nhật 2014 - bluebird cho đến nay là nhanh nhất và là ứng dụng có khả năng sửa lỗi tốt nhất hiện nay.
Benjamin Gruenbaum

19

Một lời hứa là một "điều" đại diện cho kết quả "cuối cùng" của một hoạt động để nói. Điểm cần lưu ý ở đây là, nó trừu tượng hóa các chi tiết về thời điểm xảy ra và cho phép bạn tập trung vào những gì sẽ xảy ra sau khi điều gì đó xảy ra. Điều này sẽ dẫn đến mã sạch, có thể bảo trì trong đó thay vì có một cuộc gọi lại bên trong một cuộc gọi lại bên trong một cuộc gọi lại, mã của bạn sẽ trông giống như:

 var request = new Promise(function(resolve, reject) {
   //do an ajax call here. or a database request or whatever.
   //depending on its results, either call resolve(value) or reject(error)
   //where value is the thing which the operation's successful execution returns and
   //error is the thing which the operation's failure returns.
 });

 request.then(function successHandler(result) {
   //do something with the result
 }, function failureHandler(error) {
  //handle
 });

Lời hứa 'spec nói rằng một lời hứa

then

phương thức sẽ trả về một lời hứa mới được thực hiện khi thành công được đưa ra hoặc cuộc gọi lại failHandler kết thúc. Điều này có nghĩa là bạn có thể xâu chuỗi các lời hứa khi bạn có một tập hợp các tác vụ không đồng bộ cần được thực hiện và được đảm bảo rằng trình tự các hoạt động được đảm bảo giống như khi bạn đã sử dụng các cuộc gọi lại. Vì vậy, thay vì chuyển một cuộc gọi lại bên trong một cuộc gọi lại bên trong một cuộc gọi lại, mã với các lời hứa được xâu chuỗi trông giống như:

var doStuff = firstAsyncFunction(url) {
                return new Promise(function(resolve, reject) {
                       $.ajax({
                        url: url,
                        success: function(data) {
                            resolve(data);
                        },
                        error: function(err) {
                             reject(err); 
                        } 
                  });
               };
doStuff
  .then(secondAsyncFunction) //returns a promise
  .then(thirdAsyncFunction); //returns a promise

Để biết thêm về những lời hứa và lý do tại sao chúng cực hay, hãy xem blog của Domenic: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/


12

Hướng dẫn mới này về Lời hứa từ tác giả của PouchDB có lẽ là tốt nhất tôi từng thấy ở bất cứ đâu. Nó khôn ngoan bao gồm các lỗi tân binh cổ điển cho bạn thấy các mẫu sử dụng chính xác và thậm chí một vài mẫu chống vẫn được sử dụng phổ biến - ngay cả trong các hướng dẫn khác !!

Thưởng thức!

Tái bút Tôi đã không trả lời một số phần khác của câu hỏi này vì chúng đã được những người khác bảo vệ tốt.


Lời xin lỗi duy nhất của tôi cho điều này là buộc bạn phải đọc sự hài hước ở phần cuối của Lỗi nâng cao # 4.
Tony O'Hagan

Trong thực tế, mã trong hướng dẫn mà họ tuyên bố là một antipotype cần lồng nhau cho vòng lặp và điều kiện, và không thể dễ dàng làm phẳng như họ đề xuất.
Bergi

Lỗi nâng cao # 4 cũng có thể được giải quyết bằng cách sử dụng số lượng lớn hơn các cách tiếp cận khác nhau, xem Làm thế nào để tôi truy cập kết quả lời hứa trước đó trong chuỗi .then ()? ( mô hình đóng cửa mà họ đề xuất dường như không phổ biến lắm).
Bergi

Tôi nghĩ rằng câu trả lời chỉ liên kết này tốt hơn nên là một nhận xét. Vui lòng đặt ít nhất những điểm chính của bài viết đó trong câu trả lời của bạn ở đây.
Bergi

7

Mike Taulty có một loạt các video , mỗi dài chưa đầy mười phút, mô tả cách thư viện WinJS Promise hoạt động.

Các video này khá nhiều thông tin và Mike quản lý để thể hiện sức mạnh của API Promise với một vài ví dụ mã được chọn tốt.

var twitterUrl = "http://search.twitter.com/search.json?q=windows";
var promise = WinJS.xhr({ url: twitterUrl });

 promise = promise.then(
     function (xhr) {
     },
     function (xhr) {
         // handle error
     });

Việc xử lý các trường hợp ngoại lệ được xử lý như thế nào là đặc biệt tốt.

Mặc dù có các tài liệu tham khảo WinJs, đây là một loạt video quan tâm chung, bởi vì API Promise tương tự nhau trên nhiều triển khai của nó.

vui lòng phúc đáp là một triển khai Promise nhẹ, vượt qua bộ thử nghiệm Promise / A +. Tôi khá thích API, vì nó có phong cách tương tự giao diện WinJS.

Cập nhật tháng 4 năm 2014

Ngẫu nhiên, thư viện WinJS hiện là nguồn mở .


1
+1. Đây là ví dụ đầu tiên tôi thấy có ý nghĩa với tôi sử dụng trực quan. Bằng cách nào đó bộ não của tôi không thể phân tích tất cả các deferredsresolvedeferred.promise.thenvà predefining của promiseActionstrong tài liệu thư viện Q phổ biến. Bất kỳ cơ hội nào bạn biết điều này đơn giản cho Node.js ?
Redsandro

1
@noel cảm ơn bạn đã chia sẻ liên kết trên, đây là một loạt bài giới thiệu tuyệt vời cho những lời hứa và tôi đồng ý rằng các chi tiết cụ thể của WinJS không liên quan vì cách tiếp cận / chủ đề chung là phổ biến.
arcseldon

Ví dụ tốt đẹp. Ngoài ra, tôi đã sửa liên kết đầu tiên của bạn đã chết
st némauwg

5

Một ưu điểm khác của lời hứa là xử lý lỗi và ném và bắt ngoại lệ tốt hơn nhiều so với cố gắng xử lý điều đó bằng các cuộc gọi lại.

Các bluebird thư viện cụ hứa hẹn và cung cấp cho bạn dấu vết ngăn xếp dài tuyệt vời, rất nhanh, và cảnh báo về các lỗi còn tự do. Nó cũng nhanh hơn và sử dụng ít bộ nhớ hơn các thư viện hứa hẹn khác, theo http://bluebirdjs.com/docs/benchmark.html


4

Chính xác thì một lời hứa là gì?

Một lời hứa chỉ đơn giản là một đối tượng đại diện cho kết quả của hoạt động không đồng bộ. Một lời hứa có thể ở bất kỳ trong 3 trạng thái sau:

Đang chờ xử lý :: Đây là trạng thái ban đầu, có nghĩa là lời hứa không được thực hiện cũng không bị từ chối.

hoàn thành :: Điều này có nghĩa là lời hứa đã được thực hiện, có nghĩa là giá trị được thể hiện bằng lời hứa đã sẵn sàng để được sử dụng.

bị từ chối :: Điều này có nghĩa là các hoạt động thất bại và do đó không thể thực hiện lời hứa. Ngoài các tiểu bang, có ba thực thể quan trọng liên quan đến những lời hứa mà chúng ta thực sự cần phải hiểu

  1. Hàm thực thi :: Hàm thực thi xác định thao tác async cần được thực hiện và kết quả được thể hiện bằng lời hứa. Nó bắt đầu thực thi ngay khi đối tượng hứa được khởi tạo.

  2. giải quyết :: giải quyết là một tham số được truyền cho chức năng thực thi và trong trường hợp người thực thi chạy thành công thì giải quyết này được gọi là truyền kết quả.

  3. từ chối :: từ chối là một tham số khác được truyền cho hàm thực thi và nó được sử dụng khi chức năng thực thi không thành công. Lý do thất bại có thể được thông qua để từ chối.

Vì vậy, bất cứ khi nào chúng tôi tạo một đối tượng lời hứa, chúng tôi sẽ cung cấp Executor, Resolve và Reject.

Tham khảo :: Lời hứa


0

Gần đây tôi cũng đã xem xét các lời hứa trong node.js. Đến nay, if.js dường như là hướng đi do tốc độ và việc sử dụng tài nguyên của nó, nhưng tài liệu về q.js đã cho tôi hiểu rõ hơn rất nhiều. Vì vậy, sử dụng if.js nhưng tài liệu q.js để hiểu chủ đề.

Từ readme q.js trên github:

Nếu một hàm không thể trả về giá trị hoặc ném ngoại lệ mà không chặn, thay vào đó, nó có thể trả về một lời hứa. Lời hứa là một đối tượng đại diện cho giá trị trả về hoặc ngoại lệ được ném mà hàm cuối cùng có thể cung cấp. Một lời hứa cũng có thể được sử dụng như một proxy cho một đối tượng ở xa để khắc phục độ trễ.


0

Đối tượng Promise đại diện cho sự hoàn thành hoặc thất bại của một hoạt động không đồng bộ.

Vì vậy, để thực hiện lời hứa, bạn cần hai phần: -

1. Tạo lời hứa:

Hàm tạo hứa hẹn chấp nhận một hàm gọi là hàm thực thi có 2 tham số giải quyết và từ chối.

function example(){
   return new Promise (function(resolve , reject){   //return promise object
      if(success){
         resolve('success');  //onFullfiled
      }else{
         reject('error');     //onRejected
      }
   })
}

2. Xử lý Promise:

Đối tượng Promise có 3 phương thức để xử lý các đối tượng hứa hẹn: -

1.Promise.prototype.catch (onRejection)

2.Promise.prototype.then (onFullfiled)

3.Promise.prototype.finally (onFullfiled, onRejection)

example.then((data) =>{
  //handles resolved data
  console.log(data); //prints success     
}).catch((err) => {
  //handles rejected error 
  console.log(err);  //prints error
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.