如何在 try 块内的函数内的 setInterval 内抛出错误?

How to throw an error inside a setInterval that is inside a function that is inside a try block?

考虑以下代码:

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() 回调中没有,为什么会这样?

所以,您没有捕捉到错误是因为代码通常 运行 是同步的,一次一行。但是 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()

更多信息:

它抛出一个错误,但没有被正确捕获(因为错误没有在 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 多次。可能的替代方案是使用事件发射器,使用 Observable 库(如 RxJS)或者甚至编写异步迭代器。

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

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

那么你可以await waitForTimer:

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