【问题标题】:How to throw an error inside a setInterval that is inside a function that is inside a try block?如何在 try 块内的函数内的 setInterval 内引发错误?
【发布时间】:2021-11-13 11:42:39
【问题描述】:

考虑下面的代码:

async function why(){
    try {
        function noWait(callback) {
            callback();
        }
        async function waitForTimer(callback) {
            var timer = setInterval(()=>{
              clearInterval(timer);
              callback()
            }, 10);
        }
        waitForTimer(()=>{
            throw "this is error??"
        });
        noWait(()=>{
            throw"this is error!!"
        });
    } catch (err) {
        console.log(err);
    }
}

why()

如何在 setInterval 函数中抛出错误并在 catch 块中捕获? noWait() 回调中抛出的错误有效,但 waitForTimer() 回调中没有,为什么会这样?

【问题讨论】:

    标签: javascript promise try-catch setinterval throw


    【解决方案1】:

    它抛出一个错误,但它没有被正确捕获(因为错误没有在try 块内抛出)。一种替代方法是在您的回调中使用 trycatch

    function why() {
      function noWait(callback) {
        try {
          callback();
        } catch (e) {
          //error here
        }
      }
    
      function waitForTimer(callback) {
        var timer = setInterval(() => {
          try {
            clearInterval(timer);
            callback()
          } catch (e) {
            //caught error here
          }
        }, 10);
      }
      waitForTimer(() => {
        throw "this is error??"
      });
      noWait(() => {
        throw "this is error!!"
      });
    }
    

    但这当然很糟糕。

    setInterval 使用内置异步功能可能有点棘手。它不适合Promise,因为您可以多次使用resolve/reject。可能的替代方法是使用 Event Emitter,使用 Observable 库(如 RxJS),甚至可能编写异步迭代器。

    在这个例子中,因为你使用setInterval 作为setTimeout 基本上......你可以把它包装成一个承诺。

    let timeout = ms => new Promise(res => setTimeout(res, ms));
    async waitForTimer function(){
        await timeout(10);
        callback();
    }
    

    那你awaitwaitForTimer就可以抓到了:

    let timeout = ms => new Promise(res => setTimeout(res, ms));
    async function why() {
      try {
        function noWait(callback) {
          callback();
        }
        async function waitForTimer(callback) {
          await timeout(10);
          callback();
        }
        await waitForTimer(() => {
          throw "this is error??"
        });
        noWait(() => {
          throw "this is error!!"
        });
      } catch (err) {
        console.log(err);
      }
    }
    
    why()

    你仍然可以像你一样抓住另一个(除非你将它们移动到单独的 try 块中,否则你不会同时抓住它们)。

    timeout 函数也可以写成 setInterval 如果你愿意,但这有点不必要。

    let timeout = ms => new Promise(res => {
        let timer = setInterval(() => {
            clearInterval(timer);
            res();
        }, ms);
    });
    

    【讨论】:

      【解决方案2】:

      所以,您没有发现错误是因为代码通常是同步运行的,一次一行。但是 waitForTimer 是一个异步函数,这意味着它会被调用,但在后台运行。您想要异步捕获的任何内容都需要包装在异步函数中或使用 Promises。

      在这种情况下,为什么已经是异步函数了!所以你可以这样做:

      async function why(){
          try {
              function noWait(callback) {
                  callback();
              }
              async function waitForTimer(callback) {
                  var timer = setInterval(()=>{
                    clearInterval(timer);
                    callback()
                  }, 10);
              }
              await waitForTimer(()=>{
                  throw "this is error??"
              });
              noWait(()=>{
                  throw"this is error!!"
              });
          } catch (err) {
              console.log(err);
          }
      }
      
      why()
      

      或者

      async function why(){
          try {
              function noWait(callback) {
                  callback();
              }
              async function waitForTimer(callback) {
                  var timer = setInterval(()=>{
                    clearInterval(timer);
                    callback()
                  }, 10);
              }
              waitForTimer(()=>{
                  throw "this is error??"
              }).catch(err => console.log(err));
              noWait(()=>{
                  throw"this is error!!"
              });
          } catch (err) {
              console.log(err);
          }
      }
      
      why()
      

      欲了解更多信息:How do I catch thrown errors with async / await?

      【讨论】:

        猜你喜欢
        • 2018-12-05
        • 2011-02-23
        • 2021-05-07
        • 1970-01-01
        • 1970-01-01
        • 2021-09-09
        • 2023-03-23
        • 1970-01-01
        • 2020-02-03
        相关资源
        最近更新 更多