Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.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 RxJS重试未按预期运行?_Javascript_Rxjs_Reactive Programming - Fatal编程技术网

Javascript RxJS重试未按预期运行?

Javascript RxJS重试未按预期运行?,javascript,rxjs,reactive-programming,Javascript,Rxjs,Reactive Programming,我很难让RxJS的重试操作符与map操作符一起工作 本质上,我试图做的是获取一个值流(在本例中,GitHub用户用于测试目的),并对每个值对该值执行一些操作 但是,我希望能够以允许我为该操作设置有限重试次数的方式处理错误。我还假设RxJS异步处理这样的事情 Rx.Observable.fromPromise(jQuery.getJSON("https://api.github.com/users")) .concatAll(x => Rx.Observable.of(x)) .map(x

我很难让RxJS的重试操作符与map操作符一起工作

本质上,我试图做的是获取一个值流(在本例中,GitHub用户用于测试目的),并对每个值对该值执行一些操作

但是,我希望能够以允许我为该操作设置有限重试次数的方式处理错误。我还假设RxJS异步处理这样的事情

Rx.Observable.fromPromise(jQuery.getJSON("https://api.github.com/users"))
.concatAll(x => Rx.Observable.of(x))
.map(x => {
    if(x.id % 5 == 0) {
        console.log("error");
        return Rx.Observable.throw("error");
    }
    return x;
})
.retry(3)
.subscribe(x => console.log(x), e => console.log(e));
这就是我到目前为止得到的,但是它应该重试相同的值3次,它只打印“错误”一次,这不是我正在寻找的行为


我是否遗漏了一些琐碎的东西,或者RxJS根本不可能做到这一点?简言之,我希望异步执行对值的操作,将所述操作重试有限次,但允许其他有效操作并行进行。我仅使用Promissions实现了类似的功能,但代码相当混乱,我希望RxJS能让我的阅读变得更流畅。

我发现一些问题可能会给您带来问题:

1) 在map语句中,您通过返回一个可观察值进行抛出。如果成功案例也返回了一个可观察值,然后将其展平(使用concat、switch或merge),那么这将是合适的,但是您的成功案例只会发出一个值,而不会展平。因此,当抛出的可观察对象被返回时,它永远不会被展平,因此只会被传递并记录可观察对象

相反,您可以只做一个普通的JavaScript <代码>抛出“错误”<代码>(尽管考虑抛出一个错误对象而不是一个字符串)

2) 当重试收到错误时,它将重新订阅。如果您使用可观察对象进行抓取,这将意味着它将再次进行抓取。但是,您使用承诺进行了获取,然后仅根据该承诺创建了一个可观察的。因此,当您重新订阅observable时,它将使用第一次使用的promise对象,并且该promise已经处于解析状态。不会进行额外提取

要解决这个问题,您需要有一个可观察版本的获取。如果需要从头开始制作,它可以如下所示:

Rx.Observable.create(observer => {
  jQuery.getJSON("https://api.github.com/users")
    .then(result => {
      observer.next(result);
      observer.complete();
    }, err => {
      observer.error(err);
      observer.complete();
    });
})
function getJson (url) {
  return Rx.Observable.create(observer) => {
    jQuery.getJSON(url)
      .then(result => {
        observer.next(result);
        observer.complete();
      }, err => {
        observer.error(err);
        observer.complete();
      });
  }
}

const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint => 
  return getJson(url)
    .retry(3)
    .catch(err => Rx.Observable.of('error'));
});

Rx.Observable.forkJoin(...observables)
  .subscribe(resultArray => {
    // do whatever you need to with the results. If any of them
    //   errored, they will be represented by just the string 'error'
  });
不过,如果您打算经常这样做,我建议您创建一个函数来完成包装

编辑:


我的最终目标是基本上能够获取api URL数组,并使用每个URL启动get请求。如果get请求由于任何原因失败,它应该尝试总共3次以再次到达该端点。然而,这样一个get请求的失败不应该阻止其他请求的发生,它们应该并行发生。此外,如果一个get请求失败了3次,它应该被标记为失败,而不应该停止整个过程。到目前为止,我还没有找到一种使用RxJS的方法

然后我会这样做:

Rx.Observable.create(observer => {
  jQuery.getJSON("https://api.github.com/users")
    .then(result => {
      observer.next(result);
      observer.complete();
    }, err => {
      observer.error(err);
      observer.complete();
    });
})
function getJson (url) {
  return Rx.Observable.create(observer) => {
    jQuery.getJSON(url)
      .then(result => {
        observer.next(result);
        observer.complete();
      }, err => {
        observer.error(err);
        observer.complete();
      });
  }
}

const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint => 
  return getJson(url)
    .retry(3)
    .catch(err => Rx.Observable.of('error'));
});

Rx.Observable.forkJoin(...observables)
  .subscribe(resultArray => {
    // do whatever you need to with the results. If any of them
    //   errored, they will be represented by just the string 'error'
  });

我发现一些可能会给您带来问题的问题:

1) 在map语句中,您通过返回一个可观察值进行抛出。如果成功案例也返回了一个可观察值,然后将其展平(使用concat、switch或merge),那么这将是合适的,但是您的成功案例只会发出一个值,而不会展平。因此,当抛出的可观察对象被返回时,它永远不会被展平,因此只会被传递并记录可观察对象

相反,您可以只做一个普通的JavaScript <代码>抛出“错误”<代码>(尽管考虑抛出一个错误对象而不是一个字符串)

2) 当重试收到错误时,它将重新订阅。如果您使用可观察对象进行抓取,这将意味着它将再次进行抓取。但是,您使用承诺进行了获取,然后仅根据该承诺创建了一个可观察的。因此,当您重新订阅observable时,它将使用第一次使用的promise对象,并且该promise已经处于解析状态。不会进行额外提取

要解决这个问题,您需要有一个可观察版本的获取。如果需要从头开始制作,它可以如下所示:

Rx.Observable.create(observer => {
  jQuery.getJSON("https://api.github.com/users")
    .then(result => {
      observer.next(result);
      observer.complete();
    }, err => {
      observer.error(err);
      observer.complete();
    });
})
function getJson (url) {
  return Rx.Observable.create(observer) => {
    jQuery.getJSON(url)
      .then(result => {
        observer.next(result);
        observer.complete();
      }, err => {
        observer.error(err);
        observer.complete();
      });
  }
}

const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint => 
  return getJson(url)
    .retry(3)
    .catch(err => Rx.Observable.of('error'));
});

Rx.Observable.forkJoin(...observables)
  .subscribe(resultArray => {
    // do whatever you need to with the results. If any of them
    //   errored, they will be represented by just the string 'error'
  });
不过,如果您打算经常这样做,我建议您创建一个函数来完成包装

编辑:


我的最终目标是基本上能够获取api URL数组,并使用每个URL启动get请求。如果get请求由于任何原因失败,它应该尝试总共3次以再次到达该端点。然而,这样一个get请求的失败不应该阻止其他请求的发生,它们应该并行发生。此外,如果一个get请求失败了3次,它应该被标记为失败,而不应该停止整个过程。到目前为止,我还没有找到一种使用RxJS的方法

然后我会这样做:

Rx.Observable.create(observer => {
  jQuery.getJSON("https://api.github.com/users")
    .then(result => {
      observer.next(result);
      observer.complete();
    }, err => {
      observer.error(err);
      observer.complete();
    });
})
function getJson (url) {
  return Rx.Observable.create(observer) => {
    jQuery.getJSON(url)
      .then(result => {
        observer.next(result);
        observer.complete();
      }, err => {
        observer.error(err);
        observer.complete();
      });
  }
}

const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint => 
  return getJson(url)
    .retry(3)
    .catch(err => Rx.Observable.of('error'));
});

Rx.Observable.forkJoin(...observables)
  .subscribe(resultArray => {
    // do whatever you need to with the results. If any of them
    //   errored, they will be represented by just the string 'error'
  });

map函数返回
Rx.Observable.throw(“错误”)。这是错误的,因为下面的
retry()
随后将接收到它的包装(即作为
Observable
而不是
Observable
。您可以使用
flatMap
来纠正这一点,但是您还需要通过
Rx.Observable.of(x)
包装该值

另一个选项是
抛出新错误()
,而不是尝试
返回Rx.Observable.throw(“错误”);


确保您在正确的事情上重试

Rx.Observable.fromPromise(jQuery.getJSON("https://api.github.com/users"))
  .retry(3)
  .concatAll(x => Rx.Observable.of(x))
  ...

您的map函数返回
Rx.Observable.throw(“error”);
。这是错误的,因为下面的
retry()
随后将接收包装的值(即作为
Observable
而不是
Observable
。您可以使用
flatMap
来纠正这一点,但您还需要通过
Rx.Observable.of(x)包装该值

另一个选项是抛出新错误()
,而不是tryi