12/08/2018, 16:34

Một số sai lầm khi sử dụng promises

Đây là bài dịch, bài gốc mời các bạn xem ở đây: https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html Xin chào các JavaScripters ! Giờ đã đến lúc phải thừa nhận: Chúng ta có vấn đề với Promises. Không, không phải với với chính promises. Promises, theo như A+ Spec, vẫn là một tính ...

Đây là bài dịch, bài gốc mời các bạn xem ở đây: https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html

Xin chào các JavaScripters ! Giờ đã đến lúc phải thừa nhận: Chúng ta có vấn đề với Promises.

Không, không phải với với chính promises. Promises, theo như A+ Spec, vẫn là một tính năng tuyệt vời.

Vấn đề ở đây - như là tôi đã nhận ra sau nhiều năm, trong khi tôi nhìn thấy rất , rất nhiều programmer gặp vấn đề với PouchDB API hay những API khác sử dụng promies - đó là:

Rất nhiều người đang sử dụng promises mà không thực sự hiểu về nó.

OK, hãy xem bài quiz nhỏ mà tôi đã post trên Twitter này:

Điểm khác nhau giữa 4 dòng code sử dụng promises này là gì ?

doSomething().then(function () {
  return doSomethingElse();
});

doSomething().then(function () {
  doSomethingElse();
});

doSomething().then(doSomethingElse());

doSomething().then(doSomethingElse);

Nếu bạn biết câu trả lời, thì xin chúc mừng: Bạn là 1 promises ninja ! Và bạn có thể tắt luôn cái tab đang đọc này đi cũng được.

Với 99.99% còn lại ... Well ... Không một ai trả lời tweet của tôi có thể giải chính xác nó, và bản thân tôi cũng bị bất ngờ bởi đáp án của #3 - Đúng vậy, dù tôi là người tạo cái quiz này !

Câu trả lời sẽ nằm ở cuối bài post này, nhưng trước hết, tôi muốn biết vì sao promises lại phức tạp như vậy, và tại sao rất nhiều người - cả lính mới và cả những expert - đều mắc lỗi khi sử dụng nó.

Hãy bắt đầu với một số giả định phổ biến về promises.

Promises để làm gì ?

Ví dụ phổ biến nhất mà người mới tìm hiểu về Promises sẽ gặp đó là the pyramid of doom, với một đoạn code trông rất tởm - kéo dài liên tục cho tới khi nó chạm tới viền phải màn hình.

Promises - thực tế, giải quyết được vấn đề trên - không đơn giản chỉ là để làm đẹp indentation. Như đã được giải thích trong "Redemtion from callback hell", vấn đề thực sự của callback đó là việc nó lấy đi của ta return và throw. Thay vào đó, toàn bộ flow chương trình của ta bị phụ thuộc vào side effect : một function sẽ (ngẫu nhiên) gọi tới một function khác.

Toàn bộ mục đích của promises là cho phép chúng ta sử dụng những nguyên tắc cơ bản của ngôn ngữ mà chúng ta không dùng được với async programing : return, throw, và luồng chương trình. Nhưng đó là khi ta thực sự hiểu và biết cách sử dụng đúng lợi thế của promises.

Nhiều người cố gắng giải thích promises như là : "Oh, nó là một thứ mà chúng ta có thể chuyền xung quanh và nó đại diện cho một giá trị bất đồng bộ"

Tôi không đồng ý với cách giải thích đó cho lắm. Với tôi, promises là về cấu trúc của code và luồng chương trình. Vì vậy, tôi nghĩ rằng tốt hơn là mình sẽ chỉ ra một vài lỗi sai phổ biến dưới đây, kèm theo cách fix. Rookie mistake - như cách tôi dùng ở đây - có nghĩa là " Giờ các chú vẫn còn noob lắm :) nhưng cứ làm đi, sau này sẽ thành pro.

Rookie mistakes #1: Promisey pyramid of doom

Ta sử dụng promises để tránh cái gọi là callback hell - pyramid of doom. và nếu không cẩn thận, ta sẽ lại mắc vào một cái bẫy tương tự với promises !

Hãy quan sát cách mọi người sử dụng PouchDB - một API phụ thuộc lớn vào promises - tôi nhìn thấy rất nhiều sai lầm trong cách tiếp cận. Lỗi phổ biến nhất là cái này đây:

remotedb.allDocs({
  include_docs: true,
  attachments: true
}).then(function (result) {
  var docs = result.rows;
  docs.forEach(function(element) {
    localdb.put(element.doc).then(function(response) {
      alert("Pulled doc with id " + element.doc._id + " and added to local db.");
    }).catch(function (err) {
      if (err.name == 'conflict') {
        localdb.get(element.doc._id).then(function (resp) {
          localdb.remove(resp._id, resp._rev).then(function (resp) {
// ........................

Hóa ra ta có thể sử dụng promises giống như sử dụng callback (mặc dù nó giống như sử dụng cái cưa máy chỉ để cắt móng chân vậy).

Nếu bạn nghĩ rằng chỉ có mấy thằng lính mới mới gặp phải lỗi trên, thì bạn sẽ bất ngờ khi nhìn vào đoạn code trên trong blog chính thức của BlackBerry developer ! (P/s: To the developer: xin lỗi vì đã sử dụng code của các anh, nhưng mà nó rõ ràng quá.             </div>
            
            <div class=

0