【问题标题】:Retry, then ignore error and get source value rxjs重试,然后忽略错误并获取源值 rxjs
【发布时间】:2021-05-03 17:42:38
【问题描述】:

错误或没有错误,我想在重试后进入订阅成功处理程序。要进行测试,请注释掉 setTimeout 行。这将使 checkforText$ 总是抛出错误。我想忽略最后的错误,仍然将编辑器返回到订阅成功处理程序。

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))
    

找到文本时输出(setTimeout 未注释掉):

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

找不到文本时的目标输出(注释掉setTimeout):

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

找不到文本时的实际输出(注释掉setTimeout):

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

我尝试在 retryWhen 之后添加 catchError 以使其成为订阅成功处理程序。但它仍然没有。有什么想法吗?

【问题讨论】:

    标签: javascript rxjs retrywhen


    【解决方案1】:

    retryWhen 不可能。

    重试给定尝试后的retryWhen 运算符completes(在这种情况下,由take(3)delay(1000) 指定)。因此,如果在重试期间,您的源 observable checkForText$ 没有发出已解决的承诺或非错误值,则由 checkForText$ 和 retryWhen 组成的管道不会发出任何内容,最终流将完成后重试。

    在那之后没有办法进入成功处理程序,除非你专门让 checkForText$ 在重试期间发出一些非错误值。

    所以,如果你像下面这样在观察者中添加一个完整的回调,

    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
    );
    

    当没有找到带有 setTimeout 注释的文本时,您的情况将返回以下 -

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

    不过,您可以使用 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!")
      );
    

    这将产生:

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

    【讨论】:

    • 能够通过在 setTimeout 内拒绝承诺来引入延迟。在意识到之前尝试了其他东西的混合,比如 expand、repeatWhen 和 takeWhile 可能只会延迟拒绝。干杯
    【解决方案2】:

    正如上面的帖子所指出的,retryWhen 不可能。但是,您可以通过重试实现此目的,方法是确保您的源 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")
      );
    

    源可观察

    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())) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-23
      • 2019-04-13
      • 1970-01-01
      • 2012-03-30
      • 2016-08-07
      • 2021-03-27
      • 1970-01-01
      相关资源
      最近更新 更多