2014-10-10 15 views
11

Tôi có chuỗi lời hứa sau dưới đây và nó dường như là khá lộn xộn (Mỗi chức năng _create * trả về một lời hứa):Cách tốt nhất để xử lý Promises lồng nhau (bluebird)

return new Promise(function (resolve, reject) { 
     _this.database.transaction(function (t) { 
     _this._createExternalAccount(payment, t) 
      .then(function (externalAccount) { 
      return _this._createExternalTransaction(externalAccount, payment, t) 
       .then(function (externalTransaction) { 
       return _this._createAddress(externalAccount, payment, t) 
        .then(function (address) { 
        return _this._createTransaction(address, payment, t) 
         .then(function (transaction) { 
         return _this._createGatewayTransaction(externalTransaction, transaction, payment, t) 
          .then(function (gatewayTransaction) { 
          t.commit(); 
          resolve(bridgePayment); 
          }); 
         }); 
        }); 
       }); 
      }) 
      .error(function (bridgePayment) { 
      t.rollback(); 
      reject(bridgePayment); 
      }); 
     }); 

Tôi biết có Promise chức năng tôi có thể sử dụng như all()join() nhưng những điều này dường như chạy các hàm đồng thời mà tôi không thể làm vì sự kiên trì đối với một số bảng yêu cầu các trường từ các bảng đã tồn tại trước đó. Tôi hy vọng có một số cách để tôi làm điều gì đó như sau nhưng tôi dường như không thể tìm ra cách:

Promise.all(_this._createExternalAccount(payment, t), _this._createExternalTransaction(externalAccount, payment, t), _this._createAddress(externalAccount, payment, t)) 
    .then(function(externalAccount, externalTransaction, address) { 
     // do logic 
    }); 
+3

Bạn có thể muốn khám phá chaining:... 'P.then() sau đó() sau đó() sau đó() 'thay vì lồng nhau. – jfriend00

+0

Kiểm tra Bluebird '.map()' bạn có thể truyền '{concurrency: N}' để nó chỉ thực hiện các hoạt động 'N' tại một thời điểm – aarosil

Trả lời

6

Tôi chắc chắn chính xác những gì bạn đang yêu cầu nhưng.

  1. Nếu bạn muốn chạy một loạt các lời hứa tuần tự có this answer

    Điều quan trọng cần lưu ý là nó không phải là một mảng của lời hứa. Đó là một loạt các chức năng hứa hẹn. Đó là bởi vì lời hứa sẽ được thực thi ngay lập tức nên bạn không thể tạo ra lời hứa cho đến khi bạn cần nó.

  2. Nếu bạn không muốn đặt chúng trong mảng mặc dù điều bình thường chỉ là chuỗi chúng bình thường.

    Một lần nữa, cách dễ nhất để làm cho một bó chức năng lời hứa trả về. Sau đó, bạn chỉ

    var p = firstFunctionThatReturnsAPromise() 
    .then(secondFunctionThatReturnsAPromise) 
    .then(thirdFunctionThatReturnsAPromise) 
    .then(fourthFunctionThatReturnsAPromise) 
    

    Bạn có thể làm tổ họ cũng giống như dễ dàng

    function AOuterFunctionThatReturnsAPromise() {   
        var p = firstFunctionThatReturnsAPromise() 
          .then(secondFunctionThatReturnsAPromise) 
          .then(thirdFunctionThatReturnsAPromise) 
          .then(fourthFunctionThatReturnsAPromise); 
        return p; 
    }; 
    

    Bây giờ chức năng bên ngoài chỉ là một hàm trả về một lời hứa có nghĩa là bạn có thể áp dụng cùng một mô hình như các chức năng bên trong.

    Nếu tất nhiên những người có thể inline

    var p = function() { 
        return new Promise(resolve, reject) { 
        DoSomethingAsync(function(err, result) { 
         if (err) { 
         reject(); 
         } else { 
         resolve(result); 
        }; 
        }; 
    }).then(function() { 
        return new Promise(resolve, reject) { 
        DoSomethingAsync(function(err, result) { 
         if (err) { 
         reject(err); 
         } else { 
         resolve(result); 
        }; 
        }; 
    }).then(function() { 
        var err = DoSomethingNotAsync(); 
        if (err) { 
        return Promise.reject(err); 
        } else { 
        return Promise.resolve(); 
        } 
    }); 
    

    vv ...

3

Cá nhân, khi mọi thứ trở nên lộn xộn với phụ thuộc Tôi thích cách tiếp cận sau:

var externalAccount  = Promise.join(payment, t,         createExternalAccount), 
    externalTransaction = Promise.join(externalAccount, payment, t,     createExternalTransaction), 
    address    = Promise.join(externalAccount, payment, t,     createAddress), 
    transaction   = Promise.join(address, payment,        createTransaction), 
    gatewayTransaction = Promise.join(externalTransaction, transaction, payment, t, createGatewayTransaction); 

Làm cho mọi thứ sạch hơn, mặc dù đó là vấn đề về phong cách.

Và nếu bạn muốn làm điều gì đó sau khi bạn nhận được giá trị gatewayTransaction 's (không đồng bộ, tất nhiên), bạn có thể chỉ:

gatewayTransaction 
    .then(function (val) { 
     // do stuff 
    }) 
    .catch(function (err) { 
     // do stuff 
    }); 

Có một cái bẫy tinh tế ở đây mà bạn nên biết. Thứ tự mà các lời hứa được định nghĩa không nhất thiết là thứ tự mà các hàm được gọi. Đây là những gì phụ thuộc trông giống như:

externalAccount -----> externalTransaction -----> gatewayTransaction 
       |--> address --> transaction --| 

Mặc dù điều này là tốt cho hiệu suất, bạn có thể muốn làm cho toàn bộ thứ tự tuần tự (giống như kim tự tháp gọi lại của bạn). Trong trường hợp này, bạn có thể viết:

var externalAccount  = Promise.join(payment, t,          createExternalAccount), 
    externalTransaction = Promise.join(externalAccount, payment, t,      createExternalTransaction), 
    address    = Promise.join(externalAccount, payment, t, externalTransaction, createAddress), 
    transaction   = Promise.join(address, payment,         createTransaction), 
    gatewayTransaction = Promise.join(externalTransaction, transaction, payment, t,  createGatewayTransaction); 

Bằng cách thêm externalTransaction-address 's phụ thuộc (mặc dù giá trị của nó là không cần thiết), bạn có thể buộc nó phải tuần tự.

+2

Đây chắc chắn là những gì tôi đã nghĩ khi chúng ta thảo luận về việc thêm vào Bluebird với Gorgi và Petka . Tôi nghĩ rằng đó là một phong cách tốt đẹp –

+0

Rất vui khi được nghe, tôi thực sự thích nó. – liadmat

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