简体   繁体   English

重试,然后忽略错误并获取源值 rxjs

[英]Retry, then ignore error and get source value rxjs

Error or no error, I want to get into the subscribe success handler after retrying.错误或没有错误,我想在重试后进入订阅成功处理程序。 To test, comment out the setTimeout line.要进行测试,请注释掉 setTimeout 行。 This will make it so that checkforText$ always throws an error.这将使 checkforText$ 总是抛出错误。 I want to ignore the final error, and still return the editor to the subscribe success handler.我想忽略最后的错误,仍然将编辑器返回给订阅成功处理程序。

https://codepen.io/Spankid/pen/gOgVZEE https://codepen.io/Spankid/pen/gOgVZEE

var editor = { innerText: "" }
var editorOpened$ = of(editor) // observe editor object

function checkforText(){
    return new Promise((resolve,reject) => {
        console.log('checking for text',editor)
    
        if (editor.innerText == ""){
            reject('No text');
        } else {
            resolve(editor)
        }
    })
}

var checkForText$ = defer( () => from(checkforText())) // observe text on editor object

// comment out this line out to test
setTimeout( _ => { editor.innerText = 'testing' }, 2000) 

editorOpened$.pipe( 
    switchMap(editor => 
        checkForText$.pipe(
            retryWhen(errors => {
                console.log ('no text found... retrying')
                return errors.pipe( 
                    delay(1000), 
                    take(3),
                )
            }),     
         )
     )  
).subscribe(editor => {
    console.log('FINISH CHECKING', editor)  
}, err => console.log('ERROR ',err))
    

Output when text found (setTimeout not commented out):找到文本时的 Output(setTimeout 未注释掉):

checking for text {innerText: ""}
no text found... retrying
checking for text {innerText: ""}
checking for text {innerText: "testing"}
FINISH CHECKING {innerText: "testing"}

Target output when no text found (comment out setTimeout):找不到文本时目标 output(注释掉 setTimeout):

checking for text {innerText: ""}
no text found... retrying
checking for text {innerText: ""}
checking for text {innerText: ""}
checking for text {innerText: ""}
FINISH CHECKING {innerText: ""}

Actual output when no text found (comment out setTimeout):未找到文本时的实际 output(注释掉 setTimeout):

checking for text {innerText: ""}
no text found... retrying
checking for text {innerText: ""}
checking for text {innerText: ""}
checking for text {innerText: ""}

I tried adding catchError after the retryWhen in hopes of making it into subscribe success handler.我尝试在 retryWhen 之后添加 catchError,希望将其变成订阅成功处理程序。 But it still does not.但它仍然没有。 Any ideas?有任何想法吗?

It's not possible with retryWhen . retryWhen是不可能的。

The retryWhen operator completes after retrying for given attempts (in this case, specified by take(3) along with delay(1000) ). retryWhen运算符在重试给定尝试后completes (在这种情况下,由take(3)delay(1000)指定)。 So, if during the retries, your source observable which is checkForText$ does not emit a resolved promise or a non-error value, the pipeline consisting of checkForText$ and retryWhen will not emit anything and ultimately the stream will complete post retries.因此,如果在重试期间,您的可观察源checkForText$没有发出已解析的 promise 或非错误值,则由 checkForText$ 和 retryWhen 组成的管道不会发出任何内容,最终 stream 将完成后重试。

There's no way to get into the success handler after that unless you specifically make the checkForText$ to emit some non-error value during the retries.在那之后没有办法进入成功处理程序,除非您专门让 checkForText$ 在重试期间发出一些非错误值。

So, if you add a complete callback in your observer like below,因此,如果您在观察者中添加一个完整的回调,如下所示,

editorOpened$.pipe( 
    switchMap(editor => 
        checkForText$.pipe(
            retryWhen(errors => {
                console.log ('no text found... retrying')
                return errors.pipe( 
                    delay(1000), 
                    take(3),
                )
            }),     
         )
     )  
).subscribe(editor => {
    console.log('FINISH CHECKING', editor)  
  }, 
  (err) => console.log('ERROR ',err), 
  () => console.log('I'm done!') //The complete handler
);

Your case when no text found with setTimeout commented will return following -当您没有找到带有 setTimeout 注释的文本时,您的情况将返回以下 -

checking for text {innerText: ""}
no text found... retrying
checking for text {innerText: ""}
checking for text {innerText: ""}
checking for text {innerText: ""}
I'm done!

You can however achieve this using retry but I'm not sure how delay can be introduced just with retry .但是,您可以使用retry来实现此目的,但我不确定如何仅使用retry来引入延迟。

editorOpened$
  .pipe(
    switchMap(editor =>
      checkForText$.pipe(
        retry(3),
        catchError(errors => of(editor))
      )
    )
  )
  .subscribe(
    editor => {
      console.log("FINISH CHECKING", editor);
    },
    err => console.log("ERROR ", err),
    () => console.log("I'm done!")
  );

This will produce:这将产生:

checking for text {innerText: ""}
checking for text {innerText: ""}
checking for text {innerText: ""}
checking for text {innerText: ""}
FINISH CHECKING {innerText: ""}
I'm done!

As post above points out, its not possible with retryWhen .正如上面的帖子所指出的, retryWhen 是不可能的 You can however achieve this using retry , by ensuring that your source observable handles any delay.但是,您可以使用 retry 来实现这一点,方法是确保您的源 observable 处理任何延迟。

editorOpened$
  .pipe(
    mergeMap(editor =>
      checkForText$.pipe(
        retry(3),
        catchError(errors => of(editor))
      )
    )
  )
  .subscribe(
    editor => console.log("Finish", editor);,
    err => console.log("Error", err),
    _ => console.log("Complete")
  );

Source observable源可观察

function checkforText(){
    return new Promise((resolve,reject) => {
        console.log('checking for text', editor)
        if (editor.innerText == ""){
            setTimeout(_=> reject('No text'), 500); // reject after half a second
        } else {
            resolve(editor)
        }
    })
}

var checkForText$ = defer(_=> from(checkforText())) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM