2016-08-08 13 views
0

私は、別の観測値から1つの観測値の値を検索する簡単な検索スキームを実装しようとしています。以下buildLookup機能は、観察からの値を使用してルックアップテーブルを構築します。rxjs - observablesで検索する

その後、私持っている、これは、この関数の結果を使用して別の関数(約束)
// Build lookup table from an observable. 
// Returns a promise 
function buildLookup(obs, keyName, valName) { 
    const map = new Map(); 
    obs.subscribe((obj) => map.set(obj[keyName], obj[valName])); 

    // use concat to force wait until `obs` is complete 
    return obs.concat(Observable.from([map])).toPromise(); 
} 

:何らかの理由で

// Lookup in a previously built lookup table. 
function lookup(source, prom, keyName, fieldName) { 
    return source.map((obj) => { 
     const prom2 = prom.then((map) => { 
      return lodash.assign({}, obj, { [fieldName]: map.get(String(obj[keyName])) }); 
     }); 
     return Observable.fromPromise(prom2); 
    }) 
    .flatMap((x) => x); 
} 

、この実装がうまくいかず、お互いルックアップが失敗するようです。もし誰かが上で私を導くことができます:

  • は、このコードで何が間違っている、と
  • このような何かを実装するためのより良い方法があるかどうか?

ありがとうございました!

"use strict"; 
const lodash = require("lodash"); 
const rxjs = require("rxjs"); 
const chai = require("chai"); 

const Observable = rxjs.Observable; 
const assert = chai.assert; 
const assign = lodash.assign; 

describe("search",() => { 
    it("simple search", (done) => { 
     let nextId = 1, nextId2 = 1; 
     const sourceObs = Observable.interval(5).take(5).map((i) => { 
      const id = nextId++; 
      return { id: `${id}` }; 
     }); 

     const searchableObs = Observable.interval(5).take(5).map((i) => { 
      const id = nextId2++; 
      return Observable.from([ 
       { id: `${id}`, code: "square", val: id * id }, 
      ]); 
     }).flatMap((x) => x); 


     const results = []; 
     const verifyNext = (x) => { 
      assert.isDefined(x); 
      results.push(x); 
     }; 
     const verifyErr = (err) => done(err); 
     const verifyComplete =() => { 
      assert.equal(results.length, 5); 
      try { 
       results.forEach((r) => { 
        console.log(r); 
        // assert.equal(r.val, r.id*r.id); <== *** fails *** 
       }); 
      } catch (err) { 
       done(err); 
      } 
      done(); 
     }; 

     // main 
     const lookupTbl = buildLookup(searchableObs, "id", "val"); // promise that returns a map 
     lookup(sourceObs, lookupTbl, "id", "val") 
      .subscribe(verifyNext, verifyErr, verifyComplete) 
      ; 
    }); 

}); 


// output 
// { id: '1', val: 1 } 
// { id: '2', val: undefined } 
// { id: '3', val: 9 } 
// { id: '4', val: undefined } 
// { id: '5', val: 25 } 

答えて

0

だから、物事の束がここに対処する:

私は以下の私のテストコードを添付しています。

主な問題は、sourceObssearchableObsのオブザーバブルで副作用を起こしていて、公開されていないため、複数回サブスクリプションするために副作用が発生するためです。例えば、私のようなマップを取得:

{"1" => 1, "4" => 16, "7" => 49, "12" => 144}

をしかし、あなたはとても些細な何かをやっているあなたは本当には可変変数を使用してはならないこと。あなたが適切な観測を作成する方法である、ここで、この問題を解決するには


const sourceObs = Rx.Observable.range(1, 5).map(i => ({ id: `${i}` })); 

const searchableObs = Rx.Observable.range(1, 5).map(i => 
    ({ id: `${i}`, code: "square", val: i * i }) 
); 

range戻っ番号1、2、以来、変数を使用する理由はありません... そして、 o.map(_ => Rx.Observable.from(...)).concatMap(e => e)の使用は、私がここにいるが、これはあなたのCORの簡易版です...


oとして本当にただ同じです簡潔で不器用な機能:

これはあなたのために働くはずです。

+0

ありがとうございます@Ptival、非常に便利です。 – PKK

関連する問題