Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 多个观测值协同工作_Angular_Reactjs_React Native_Rxjs_Observable - Fatal编程技术网

Angular 多个观测值协同工作

Angular 多个观测值协同工作,angular,reactjs,react-native,rxjs,observable,Angular,Reactjs,React Native,Rxjs,Observable,我有一个输入,当用户键入时,它会执行实时搜索。例如,假设他搜索了以下内容: 汽车 结果将是: [ { id: "1" name: "Ferrari" }, { id: "2" name: "Porsche" } ] [ { id: "1" name: "Ferrari" }, { id: "2" name: "Porsche" } ] [ { id: "3" name: "eg

我有一个输入,当用户键入时,它会执行实时搜索。例如,假设他搜索了以下内容:

汽车

结果将是:

[
  {
    id: "1"
    name: "Ferrari"
  },
  {
    id: "2"
    name: "Porsche"
  }
]
[
  {
    id: "1"
    name: "Ferrari"
  },
  {
    id: "2"
    name: "Porsche"
  }
]
[
  {
    id: "3"
    name: "egg"
  },
  {
    id: "4"
    name: "cheese"
  }
]
[
  {
    id: "5"
    name: "star"
  },
  {
    id: "6"
    name: "sky"
  }
]
我成功地做到了这一点,以下是如何做到的:

class WordComponent {
  word: Subject<string> = new Subject<string>();
  result: any[] = [];

  constructor(private http: Http) {
    this.subscribe();
  }

  subscribe(): void {
    this.word.debounceTime(400)
      .distinctUntilChanged()
      .switchMap((word: string): Observable<any[]> => this.http.get(word))
      .subscribe((result: any[]): any[] => this.result = result);
  }

  search(event: any): void {
    this.word.next(event.target.value);
  }

}
食物的结果是:

[
  {
    id: "1"
    name: "Ferrari"
  },
  {
    id: "2"
    name: "Porsche"
  }
]
[
  {
    id: "1"
    name: "Ferrari"
  },
  {
    id: "2"
    name: "Porsche"
  }
]
[
  {
    id: "3"
    name: "egg"
  },
  {
    id: "4"
    name: "cheese"
  }
]
[
  {
    id: "5"
    name: "star"
  },
  {
    id: "6"
    name: "sky"
  }
]
sun的结果是:

[
  {
    id: "1"
    name: "Ferrari"
  },
  {
    id: "2"
    name: "Porsche"
  }
]
[
  {
    id: "1"
    name: "Ferrari"
  },
  {
    id: "2"
    name: "Porsche"
  }
]
[
  {
    id: "3"
    name: "egg"
  },
  {
    id: "4"
    name: "cheese"
  }
]
[
  {
    id: "5"
    name: "star"
  },
  {
    id: "6"
    name: "sky"
  }
]
并合并每个单词的结果,在这种情况下,它将如下所示:

[
  [{
      id: "1"
      name: "Ferrari"
    },
    {
      id: "2"
      name: "Porsche"
    }
  ],
  [{
      id: "3"
      name: "egg"
    },
    {
      id: "4"
      name: "cheese"
    }
  ],
  [{
      id: "5"
      name: "star"
    },
    {
      id: "6"
      name: "sky"
    }
  ]
]
subscribe(): void {
  this.word.debounceTime(400)
  .distinctUntilChanged()
  .switchMap((words: string): Observable<any[]> => 
    Observable.forkJoin(words.split(' ').map(word => this.http.get(word))) 
  )
  .map(arrayWithArrays => [].concat(arrayWithArrays)
  .subscribe((result: any[]): any[] => this.result = result);
 }
但假设用户在键入所有单词并执行搜索后,希望更改其中一个单词。只有对已更改单词的搜索需要重新进行,最终结果的合并也必须重新进行


我仍然不知道rxjs的所有特性,也不知道实现这一点的理想方式是什么。如果你想要一个参考,这个网站有一个非常相似的搜索引擎。

我想你需要这样的东西:

[
  [{
      id: "1"
      name: "Ferrari"
    },
    {
      id: "2"
      name: "Porsche"
    }
  ],
  [{
      id: "3"
      name: "egg"
    },
    {
      id: "4"
      name: "cheese"
    }
  ],
  [{
      id: "5"
      name: "star"
    },
    {
      id: "6"
      name: "sky"
    }
  ]
]
subscribe(): void {
  this.word.debounceTime(400)
  .distinctUntilChanged()
  .switchMap((words: string): Observable<any[]> => 
    Observable.forkJoin(words.split(' ').map(word => this.http.get(word))) 
  )
  .map(arrayWithArrays => [].concat(arrayWithArrays)
  .subscribe((result: any[]): any[] => this.result = result);
 }
subscribe():void{
此.word.debounceTime(400)
.distinctUntilChanged()
.switchMap((字:字符串):可观察=>
Observable.forkJoin(words.split(“”).map(word=>this.http.get(word)))
)
.map(arrayWithArrays=>[].concat(arrayWithArrays)
.subscribe((结果:any[]):any[]=>this.result=result);
}

我想出了一个巨大但不全面的解决方案:

在这里拉小提琴:

Rx.Observable.prototype.combineAllCont=函数(){
设lastValues=[];
返回Rx.Observable.create(obs=>{
设i=0;
让订阅=此。订阅(流=>{
常数streamIndex=i;
subscription.add(stream.subscripte)(res=>{
lastValues[streamIndex]=res;
obs.next(最新值);
}));
i++;
});
退订;
});
}
/**要演示的内容**/
让搜索框=[
'',
“汽车”,
“汽车”,
“汽车食品”,
“汽车食品太阳”,
“猫粮太阳”,
“猫太阳”
]
函数性能搜索(word){
返回接收可观察延迟(()=>{
console.log('发送对'+word'的搜索);
返回Rx.observative.of({
字:字,
结果:word.split(“”)
});
})
}
设searchBoxStream=Rx.可观测间隔(500)
.take(searchBox.length*2)
.map((i)=>searchBox[i%searchBox.length]);
/**好东西从这里开始**/
让wordsStream=searchBoxStream
.map((str)=>str.trim().split(“”).filter((w)=>w.trim()!=“”));
让wordSearchSubjects=[];
让wordSearchStreamSubject=new Rx.ReplaySubject(1);
wordsStream.subscribe((单词)=>{
const nWords=单词长度;
const nsobjects=wordSearchSubjects.length;
//更新流
对于(i=0;iperformSearch(w))
.concat(Rx.Observable.of(false))//结束信号
)
wordSearchSubjects[i].next(words[i]);
}
//删除流
for(i=nWords;iarr.filter((r)=>r!==false));
resultingStream=wordSearchStream
.map((arr)=>{
设ret=[];
arr.forEach(搜索=>{
ret.push(搜索结果);
});
返回ret;
})
.subscribe((arr)=>console.log(arr));
需要改进的事项:

  • 我必须使用一个自定义的
    combineAll
    实现,它不会等待原始流完成。如果没有正确实现,这可能会导致内存泄漏,并且应该删除完成的内部订阅(现在不会)
  • 必须改进单词变化检测:删除中间的单词会使一半的单词再次被搜索

  • 也许有一个更好、更直接的解决方案,但我可以想出这个乱七八糟的问题。感觉非常不舒服/危险。

    我认为解决方案非常清楚。首先,我们必须对单词执行一个diff算法。需要删除陈旧的单词,只需要请求新单词

    唯一真正的问题是我们如何以最干净的方式实现它,而不存在任何数据竞争。因此,我提出了一个实现:

    searchTags$.pipe(
    扫描((对,标记)=>[对[1]| |对[0],标记],[]),
    concatMap(([prevTags,nextTags])=>
    来自(createActions(prevTags,nextTags))
    ),
    减少([])的((集合$,操作)=>集合$.pipe(操作),
    开关映射(流=>流)
    ).subscribe(集合=>{/*…*/})
    函数createActions(prevTags、nextTags){
    nextTags.reduce((操作、标记)=>{
    if(isOld(前置标签、标签)){
    动作。推(移除动作(标签));
    }
    如果(isNew(prevTags,tag)){
    actions.push(addAction(tag));
    }
    返回动作;
    }, []);
    }
    函数removeAction(标记){
    返回映射(集合=>{collection[tag]=undefined;返回集合;});
    }
    函数addAction(标记){
    返回switchMap(collection=>requestTag(tag).pipe(map(
    res=>{collection[tag]=res;返回集合;}
    )));
    }
    

    这是我能做的最短的了

    我认为这是一个非常有趣的问题,但我不确定只使用rxjs操作符就可以解决这个问题。。。提取流中的单个单词并找出哪些单词发生了变化,这是一个非常复杂的逻辑。我想知道这是如何解决的。我同意这是一个很好的问题,我会在有时间的时候尽快给出答案;)我认为罗宾·迪克霍夫的回答是一个很好的开始……这样你就可以重新调用那些没有c的单词