0

错误或没有错误,我想在重试后进入订阅成功处理程序。要进行测试,请注释掉 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,希望将其变成订阅成功处理程序。但它仍然没有。有任何想法吗?

4

2 回答 2

1

这是不可能的retryWhen

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

在那之后没有办法进入成功处理程序,除非您专门让 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!
于 2021-05-03T19:42:38.380 回答
0

正如上面的帖子所指出的,retryWhen 是不可能的。但是,您可以使用 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")
  );

源可观察

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())) 
于 2021-05-07T23:15:04.107 回答