2015-04-29 23 views
12

Tôi mới đến RxJS và FRP nói chung. Tôi đã có ý tưởng chuyển đổi một chuỗi lời hứa hiện có trong ứng dụng ExpressJS thành một quan sát thực hành. Tôi biết rằng điều này có lẽ không phải là ví dụ tốt nhất nhưng có lẽ ai đó có thể giúp giảm bớt ánh sáng.lời hứa Chaining với RxJS

Những gì tôi đang cố gắng để làm:

  1. Tôi có hai lời hứa - prom1 và prom2
  2. Tôi muốn prom1 chạy trước prom2
  3. Nếu prom1 gửi một từ chối (err), Tôi muốn hủy prom2 trước khi nó bắt đầu.
  4. Tôi muốn được thông báo lỗi prom1 trở về có sẵn cho phương pháp onerror vào người quan sát.

var prom1 = new Promise(function(resolve, reject) { 
    if (true) { 
     reject('reason'); 
    } 
    resolve(true); 
}); 

var prom2 = new Promise(function(resolve, reject) { 
    resolve(true); 
}); 

// What do I do here? This is what I've tried so far... 
var source1 = Rx.Observable.fromPromise(prom1); 
var source2 = source1.flatMap(Rx.Observable.fromPromise(prom2)); 

var subscription = source2.subscribe(
    function (result) { console.log('Next: ' + result); }, 

    // I want my error 'reason' to be made available here 
    function (err) { console.log('Error: ' + err); }, 

    function() { console.log('Completed'); }); 
+0

Các lời hứa không được "chạy", chúng không thể "bắt đầu". Ý anh là gì? – Bergi

+0

Bạn đang sử dụng thư viện hứa hẹn nào, lời hứa gốc? Nó hỗ trợ hủy bỏ như thế nào? – Bergi

+0

@Bergi - Tôi đang sử dụng https://github.com/then/promise. Khi tôi nói "chạy" hoặc "bắt đầu" tôi đoán đó là cách tôi nói khi có thể quan sát được và phát sóng tới người đăng ký. – Pathsofdesign

Trả lời

19

Nếu tôi hiểu những gì bạn đang cố gắng làm - bạn cần phải tạo ra hai quan sát thu nhập hoãn lại từ chức năng mà trở lời hứa và concat họ:

var shouldFail = false; 

function action1() { 
    return new Promise(function (resolve, reject) {  
     console.log('start action1'); 
     if (shouldFail) { 
      reject('reason'); 
     } 
     resolve(true); 
    }); 
} 

function action2() { 
    return new Promise(function (resolve, reject) {  
     console.log('start action2'); 
     resolve(true); 
    }); 
} 

var source1 = Rx.Observable.defer(action1); 
var source2 = Rx.Observable.defer(action2); 

var combination = Rx.Observable.concat(source1, source2); 

var logObserver = Rx.Observer.create(

function (result) { 
    console.log('Next: ' + result); 
}, 

function (err) { 
    console.log('Error: ' + err); 
}, 

function() { 
    console.log('Completed'); 
}); 

sau đó đối với trường hợp bình thường:

combination.subscribe(logObserver); 
// start action1 
// Next: true 
// start action2 
// Next: true 
// Completed 

Và trường hợp fisrt lời hứa không:

shouldFail = true; 
combination.subscribe(logObserver); 
// start action1 
// Error: reason 

http://jsfiddle.net/cL37tgva/

+0

Cảm ơn vì điều này!Tôi đang tìm kiếm tôi không cần phải sử dụng các defer() bit nhưng có thể vượt qua hai chức năng lời hứa trong concat() và nhận được kết quả tôi cần. Tôi có thiếu bất cứ điều gì bằng cách làm theo cách này? – Pathsofdesign

+1

Trong trường hợp đó, cả hai lời hứa sẽ được tạo ra (bắt đầu) ngay lập tức (tại thời điểm bạn gọi concat, nhưng không phải khi bạn đang thực sự đăng ký) và lời hứa thứ hai sẽ không chờ đầu tiên giải quyết trước khi bắt đầu. –

+0

Với defer() s, điều gì sẽ xảy ra nếu lời hứa thứ hai trả về trước tiên? Đây có phải là nơi concat() giữ chúng theo thứ tự không? – Pathsofdesign

5

flatMap biến một Quan sát của quan sát vào một quan sát được. Nó được sử dụng trong nhiều ví dụ với Promises vì ​​thường bạn có một quan sát và trong chức năng bản đồ bạn muốn tạo ra một lời hứa cho mỗi "mục" các emmits quan sát được. Bởi vì mọi cuộc gọi fromPromise đều tạo ra một Observable mới, điều đó làm cho nó trở thành một "quan sát được các quan sát". flatMap làm giảm độ "phẳng".

Trong ví dụ của bạn, bạn làm điều gì đó khác nhau, bạn bật một lời hứa duy nhất vào một quan sát được và muốn chuỗi nó với một quan sát (mẫu cũng tạo ra một lời hứa đơn). Concat làm những gì bạn đang tìm kiếm, nó kết nối hai quan sát với nhau.

Trường hợp lỗi sẽ làm việc như bạn mong đợi.

-1

Observable.forkJoin hoạt động tuyệt vời mảng ở đây nhận của quan sát khác.

Rx.Observable.forkJoin([this.http.get('http://jsonplaceholder.typicode.com/posts'), this.http.get('http://jsonplaceholder.typicode.com/albums')]).subscribe((data) => { 
     console.log(data); 
    }); 
Các vấn đề liên quan