Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.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
Javascript 使用可观测数据的旧式回调同步_Javascript_Rxjs - Fatal编程技术网

Javascript 使用可观测数据的旧式回调同步

Javascript 使用可观测数据的旧式回调同步,javascript,rxjs,Javascript,Rxjs,我有以下场景-4个回调函数A、B、C、D,它们是从老式的库中调用的(在库中使用一些API请求,因此执行时间未知/随机,但结果的正确顺序(按完成任务时间)对我来说很重要)-我想使用rxjs将返回的数据同步到一个可观察的结果字符串 function getData() { // --- BELOW Part can be EDIT --- let obs = new ReplaySubject(1); // this is example you can use an type f

我有以下场景-4个回调函数A、B、C、D,它们是从老式的库中调用的(在库中使用一些API请求,因此执行时间未知/随机,但结果的正确顺序(按完成任务时间)对我来说很重要)-我想使用rxjs将返回的数据同步到一个可观察的结果字符串

function getData() {

  // --- BELOW Part can be EDIT ---

  let obs = new ReplaySubject(1); // this is example you can use an type

  function A(n) { 
    let r= 'A'.repeat(n);
  }

  function B(n) {
    let r= 'B'.repeat(n);
  }

  function C(n) {
    let r= 'C'.repeat(n);
  }

  function D(n) {
    let r= 'D'.repeat(n);
    obs.next(r);
  }
  
  // --- BELOW Part can NOT be edit ---

  runLib(A,B,C,D)   
  return obs
}
在下面的代码段中,
finalResult
的值是
DDDDD
,这是错误的。
finalResult
字符串的正确值应为
aadddccccbbb

//设置-不编辑下面的代码
常数{of,Observable,ReplaySubject}=rxjs;
const{map,switchMap,delay}=rxjs.operators;//例子
//模拟库函数
函数libA(callback){setTimeout(=>callback(2),1000);}
函数libB(callback){setTimeout(=>callback(3),3000);}
函数libC(callback){setTimeout(=>callback(4),2000);}
函数libD(callback){setTimeout(=>callback(5),1500);}
函数runLib(cA、cB、cC、cD){
libA(cA);libB(cB);libC(cC);libD(cD);
}
getData().subscribe(最终结果=>{
console.log(finalResult)//这里的结果是错误的!
},e=>{},=>console.log('finished-unsubscribed');
函数getData(){
//---下面的部分可以编辑---
设obs=newreplaysubject(1);//这是一个示例,您可以使用diffrend observale类
函数A(n){
设r='A'。重复(n);
}
功能B(n){
设r='B'。重复(n);
}
函数C(n){
设r='C'。重复(n);
}
函数D(n){
设r='D'。重复(n);
obs.next(r);
}
//---下面的部分不能编辑---
runLib(A,B,C,D)
返回obs
}

在这种情况下,最好将库函数包装为返回
可观察的
,然后使用
forkJoin
等待所有结果

我获取了您的代码并对其进行了修改以获得所需的结果,您需要:

  • 在每个回调中,将结果发送给主题
  • 返回一个
    可观察的
    ,等待
    n
    发射-在本例中为4
  • 将排放映射到单个字符串中
  • 最后的
    getData
    函数如下所示:

    函数getData(){ //---下面的部分可以编辑--- const result$:Subject=new Subject(); const obs=result$.asObservable().pipe( bufferCount(4),//或任何所需的回调次数 映射((结果:字符串[])=>results.join(“”)) ); 函数A(n){ 让r=“A”。重复(n); 结果$.next(r); } 功能B(n){ 让r=“B”。重复(n); 结果$.next(r); } 函数C(n){ 让r=“C”。重复(n); 结果$.next(r); } 函数D(n){ 让r=“D”。重复(n); 结果$.next(r); } //---下面的部分不能编辑--- runLib(A,B,C,D); 返回obs; }
    您可以在代码段中找到完整的代码,也可以在下面的代码段中找到完整的代码

    //设置-不编辑下面的代码
    const{Subject}=rxjs;
    const{take,bufferCount,map}=rxjs.operators;//例子
    //模拟库函数
    函数libA(callback){setTimeout(=>callback(2),1000);}
    函数libB(callback){setTimeout(=>callback(3),3000);}
    函数libC(callback){setTimeout(=>callback(4),2000);}
    函数libD(callback){setTimeout(=>callback(5),1500);}
    函数runLib(cA、cB、cC、cD){
    libA(cA);libB(cB);libC(cC);libD(cD);
    }
    getData().subscribe(最终结果=>{
    console.log(finalResult)//这里的结果是错误的!
    },e=>{},=>console.log('finished-unsubscribed');
    函数getData(){
    //---下面的部分可以编辑---
    const result$=新主题();
    函数A(n){
    让r=“A”。重复(n);
    结果$.next(r);
    }
    功能B(n){
    让r=“B”。重复(n);
    结果$.next(r);
    }
    函数C(n){
    让r=“C”。重复(n);
    结果$.next(r);
    }
    函数D(n){
    让r=“D”。重复(n);
    结果$.next(r);
    }
    const obs=结果$.pipe(
    bufferCount(4),//或任何所需的回调次数
    以(1)为例,
    映射(结果=>results.join`)
    );
    //---下面的部分不能编辑---
    runLib(A,B,C,D);
    返回obs;
    }
    以下内容如何:(我喜欢
    @Tal Ohana的
    答案,但他的解决方案中的受试者永远不会下注取消订阅,这可能会导致内存不足)

    函数getData(){ 设obs=新主题(); 函数A(n:编号){ 设r='A'。重复(n); obs.next(r); } 功能B(n:编号){ 设r='B'。重复(n); obs.next(r); } 函数C(n:编号){ 设r='C'。重复(n); obs.next(r); } 函数D(n:编号){ 设r='D'。重复(n); obs.next(r); } runLib(A,B,C,D) 回油管( 扫描((acc,值)=>acc+值), 以(4)为例, 最后() ) }
    谢谢-回答得很好-我编辑了你的答案,并将代码段改写为纯JS:)@RafiHenig在这个解决方案中,我们应该做什么来在正确的时间取消订阅?@RafiHenig实际上这不是问题,因为我可以在
    let subscriber=getData()之后以标准方式取消订阅。因此,退订不是我问题的重点。我可以取消订阅内部订阅(当结果准备好时)2。如果我在其他函数中使用
    getData().subscribe
    ,那么在它完成工作之后,它内部将没有对已用对象的引用,垃圾收集器应该删除所有-Ithink@RafiHenig他可以使用
    take
    操作员-取消订阅-我更新他的答案-问题已经解决。您能使用问题的片段并在您的答案中创建可运行的示例吗?(进入回答->编辑(在底部)查看完整的代码片段)你在Tal Ohana回答中的评论中说他在取消订阅方面有问题-我在那里问你如何解决-你知道怎么做吗?在你的回答中,你也从来没有退订过obs observable,所以这里可能也有类似的问题。。。(?)我使用function getData() { let obs = new Subject<string>(); function A(n: number) { let r = 'A'.repeat(n); obs.next(r); } function B(n: number) { let r = 'B'.repeat(n); obs.next(r); } function C(n: number) { let r = 'C'.repeat(n); obs.next(r); } function D(n: number) { let r = 'D'.repeat(n); obs.next(r); } runLib(A, B, C, D) return obs.pipe( scan((acc, value) => acc + value), take(4), last() ) }