您的位置:首页 > 娱乐 > 明星 > 如何推广网站业务_广州越秀发布_百度站长平台账号购买_数据分析培训

如何推广网站业务_广州越秀发布_百度站长平台账号购买_数据分析培训

2025/2/24 15:59:04 来源:https://blog.csdn.net/qq_24956515/article/details/143226780  浏览:    关键词:如何推广网站业务_广州越秀发布_百度站长平台账号购买_数据分析培训
如何推广网站业务_广州越秀发布_百度站长平台账号购买_数据分析培训

异步错误处理

浏览器中的异步包括定时器、事件、Promise 等。异步世界中的错误处理与同步世界中的处理不同。下面来看一些例子。

1、定时器的错误处理

之前我们介绍了如何使用 try/catch/finally 来处理错误,那异步中可以使用这些来处理错误吗?先来看一个例子:

function failAfterOneSecond() {setTimeout(() => {throw Error("Wrong!");}, 1000);
}

此函数在大约 1 秒后会抛出错误。那处理此异常的正确方法是什么?以下代码是无效的:

function failAfterOneSecond() {setTimeout(() => {throw Error("Wrong!");}, 1000);
}try {failAfterOneSecond();
} catch (error) {console.error(error.message);
}

fileOf7174.png

我们知道,try/catch 是同步的,所以没办法这样来处理异步中的错误。当传递给 setTimeout 的回调运行时,try/catch 早已执行完毕。程序将会崩溃,因为未能捕获异常。它们是在两条路径上执行的:

A: --> try/catch
B: --> setTimeout --> callback --> throw

2、事件的错误处理

我们可以监听页面中任何 HTML 元素的事件,DOM 事件的错误处理机制遵循与任何异步 Web API 相同的方案。

来看下面的例子:

const button = document.querySelector("button");button.addEventListener("click", function() {throw Error("error");
});

这里,在单击按钮后立即抛出了异常,我们该如何捕获这个异常呢?这样写是不起作用的,也不会阻止程序崩溃:

const button = document.querySelector("button");try {button.addEventListener("click", function() {throw Error("error");});
} catch (error) {console.error(error.message);
}

与前面的 setTimeout 例子一样,任何传递给 addEventListener 的回调都是异步执行的:

Track A: --> try/catch
Track B: --> addEventListener --> callback --> throw

如果不想让程序崩溃,为了正确处理错误,就必须将 try/catch 放到 addEventListener 的回调中。不过这样做并不是最佳的处理方式,与 setTimeout 一样,异步代码路径抛出的异常无法从外部捕获,并且会使程序崩溃。

下面会介绍 Promises 和 async/await 是如何简化异步代码的错误处理的。

3、onerror

HTML 元素有许多事件处理程序,例如  onclickonmouseenteronchange  等。除此之外,还有  onerror,每当  <img>  标签或  <script>  等 HTML 元素命中不存在的资源时,onerror 事件处理程序就会触发。

来看下面的例子:

<body><img src="nowhere-to-be-found.png">
</body>

当访问的资源缺失时,浏览器的控制台就会报错:

GET http://localhost:5000/nowhere-to-be-found.png
[HTTP/1.1 404 Not Found 3ms]

在 JavaScript 中,可以使用适当的事件处理程序“捕获”此错误:

const image = document.querySelector("img");image.onerror = function(event) {console.log(event);
};

或者使用 addEventListener 来监听 error 事件,当发生错误时进行处理:

const image = document.querySelector("img");image.addEventListener("error", function(event) {console.log(event);
});

此模式对于加载备用资源以代替丢失的图像或脚本很有用。不过需要记住:onerror 与 throw 或 try/catch 是无关的。

4、Promise 的错误处理

下面来通过最上面的 toUppercase 例子看看 Promise 是如何处理错误的:

function toUppercase(string) {if (typeof string !== "string") {throw TypeError("Expected string");}return string.toUpperCase();
}toUppercase(4);

对上面的代码进行修改,不返回简单的字符串或异常,而是分别使用  Promise.reject  和  Promise.resolve  来处理错误和成功:

function toUppercase(string) {if (typeof string !== "string") {return Promise.reject(TypeError("Expected string"));}const result = string.toUpperCase();return Promise.resolve(result);
}

从技术上讲,这段代码中没有任何异步的内容,但它可以很好地说明 Promise 的错误处理机制。

现在我们就可以在 then 中使用结果,并使用 catch 来处理被拒绝的 Promise:

toUppercase(99).then(result => result).catch(error => console.error(error.message));

输出结果如下:

fileOf7174.png

在 Promise 中,catch 是用来处理错误的。除了 catch 还有 finally,类似于 try/catch 中的 finally。不管 Promise 结果如何,finally 都会执行:

toUppercase(99).then(result => result).catch(error => console.error(error.message)).finally(() => console.log("Finally"));

输出结果如下:

fileOf7174.png

fileOf7174.png

需要记住,任何传递给 then/catch/finally 的回调都是由微任务队列异步处理的。 它们是微任务,优先于事件和计时器等宏任务。

5、Promise, error, throw

作为拒绝 Promise 时的最佳实践,可以传入 error 对象:

Promise.reject(TypeError("Expected string"));

这样,在整个代码库中保持错误处理的一致性。 其他团队成员总是可以访问 error.message,更重要的是可以检查堆栈跟踪。

除了  Promise.reject 之外,还可以通过抛出异常来退出 Promise 执行链。来看下面的例子:

Promise.resolve("A string").then(value => {if (typeof value === "string") {throw TypeError("Expected number!");}
});

这里使用 字符串来 resolve 一个 Promise,然后执行链立即使用 throw 断开。为了停止异常的传播,可以使用 catch 来捕获错误:

Promise.resolve("A string").then(value => {if (typeof value === "string") {throw TypeError("Expected number!");}}).catch(reason => console.log(reason.message));

这种模式在 fetch 中很常见,可以通过检查 response 对象来查找错误:

fetch("https://example-dev/api/").then(response => {if (!response.ok) {throw Error(response.statusText);}return response.json();}).then(json => console.log(json));

这里的异常可以使用 catch 来拦截。 如果失败了,并且没有拦截它,异常就会在堆栈中向上冒泡。这本身并没有什么问题,但不同的环境对未捕获的拒绝有不同的反应。

例如,Node.js 会让任何未处理 Promise 拒绝的程序崩溃:

DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

所以,最好去捕获错误。

6、使用 Promise 处理定时器错误

对于计时器或事件,不能捕获回调抛出的异常。上面有一个例子:

function failAfterOneSecond() {setTimeout(() => {throw Error("Error");}, 1000);
}// 不生效
try {failAfterOneSecond();
} catch (error) {console.error(error.message);
}

我们可以使用 Promise 来包装计时器:

function failAfterOneSecond() {return new Promise((_, reject) => {setTimeout(() => {reject(Error("Error"));}, 1000);});
}

这里通过 reject 捕获了一个 Promise 拒绝,它带有一个 error 对象。此时就可以用 catch 来处理异常了:

failAfterOneSecond().catch(reason => console.error(reason.message));

这里使用 value 作为 Promise 的返回值,使用 reason 作为拒绝的返回对象。

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com