RxJS 5任务队列,如果任务失败继续



假设我们有一个触发AJAX请求的HTML页面。我们希望确保AJAX请求按顺序执行。下一个AJAX请求不会被触发,直到前一个完成或错误。

我试图通过使用RxJS concatMap的任务队列来建模。每个AJAX请求都建模为一个Observable。如果AJAX请求成功完成,则一切正常,但是如果它出错,则队列中的下一个任务不会执行。

下面是一个例子,使用setTimeout()来模拟长时间运行的异步任务:

  function identity(observable) {
    return observable;
  }
  function createTaskQueue() {
    var subject= new Rx.Subject();
    subject
    .concatMap(identity)
    .onErrorResumeNext(Rx.Observable.of('error'))
    .subscribe(function(data) {
      console.log('onNext', data);
    }, 
    function(error) {
      console.log('onError', error);
    });
    return {
      addTask: function(task) {
        subject.next(task);
      }
    }
  }
  function createTask(data, delay) {
    return Rx.Observable.create(function(obs) {
      setTimeout(function() {
        obs.next(data);
        obs.complete();
      }, delay);
    });
  }
  function createErrorTask(data, delay) {
    return Rx.Observable.create(function(obs) {
      setTimeout(function() {
        obs.error('Error: ' + data);
        obs.complete();
      }, delay);
    });
  }
  var taskQueue = createTaskQueue();
  taskQueue.addTask(createTask(11, 500))
  taskQueue.addTask(createTask(22, 200));
  taskQueue.addTask(createErrorTask(33, 1000));
  taskQueue.addTask(createTask(44, 300));
  taskQueue.addTask(createErrorTask(55, 300));
  taskQueue.addTask(createTask(66, 300));

下面是一个可执行的例子:https://jsfiddle.net/artur_ciocanu/s6ftxwnf/.

当我运行这段代码时,下面的内容被打印到控制台: onNext 11 onNext 22 onNext error

这是预期的,但我想知道为什么其他任务,如44,55等没有执行。

我很确定我用onErrorResumeNext()做了一些愚蠢的事情,或者可能整个方法是完全错误的。

如果您阅读onErrorResumeNext的文档,

继续一个可观察序列,该序列被正常终止或被下一个可观察序列或Promise.

这意味着当你的源可观察对象遇到错误时,它将切换到你传递给onErrorResumeNext的任何内容。这里发生的事情是,Rx.of(...)在发出其值后立即终止。因此你观察到的行为

所以简而言之,你不希望这里有onErrorResumeNext

您可以代替.catch(...)可能会发出错误的流。比如:

subject
    .concatMap(obs => obs.catch(Rx.Observable.of('error')))
    .subscribe(...)

在可观察对象中错误的概念与在常规函数中相同。意思是如果你在一个普通的函数中抛出了一个错误——函数将不会返回任何东西。可观察对象也是如此——如果可观察对象发出一个错误,这意味着流已经完成,没有更多的值传入。所以,是的,它从根本上是错误的。

更好的(正确的)方法是有一个响应流,其中下一个值可以是成功响应或错误响应。如果你需要将它们分开,你可以稍后将响应流分成两个成功/错误响应。

希望对你有帮助。

最新更新