Considere el siguiente código:
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() ¿Cómo puedo arrojar errores dentro de la función setInterval y atraparlos en el bloque catch? El error arrojado en la devolución de llamada noWait() funciona, pero en la devolución de llamada waitForTimer() no, ¿por qué es así?
Lanza un error pero no se captura correctamente (porque el error no se lanza dentro del bloque de try ). Una alternativa es try de catch su devolución de llamada.
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!!" }); }Pero, por supuesto, esto es bastante malo.
setInterval puede ser un poco complicado con las funciones asincrónicas integradas. No es una buena opción para Promise ya que podría resolve / reject varias veces. Las posibles alternativas serían usar un Emisor de eventos, usar una biblioteca Observable (como RxJS) o tal vez incluso escribir un iterador asíncrono.
En este ejemplo, dado que está utilizando setInterval como setTimeout básicamente... puede envolverlo en una promesa.
let timeout = ms => new Promise(res => setTimeout(res, ms)); async waitForTimer function(){ await timeout(10); callback(); } Entonces puedes atraparlo si esperas await :
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() Todavía puedes atrapar al otro como lo haces (simplemente no atraparás a ambos a menos que los muevas a bloques de try separados).
La función de timeout de espera también se puede escribir con setInterval si lo desea, pero es un poco innecesario.
let timeout = ms => new Promise(res => { let timer = setInterval(() => { clearInterval(timer); res(); }, ms); });Entonces, no está detectando el error porque el código normalmente se ejecuta sincrónicamente, una línea a la vez. Pero waitForTimer es una función asíncrona, lo que significa que se llamará, pero se ejecutará en segundo plano. Cualquier cosa que desee capturar de forma asíncrona debe incluirse en una función asíncrona o usar Promises.
En este caso, ¿por qué ya es una función asíncrona? Entonces puedes hacer:
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()O
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()Para obtener más información: ¿Cómo detecto los errores lanzados con async/await?