ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 调试技巧 * [调试技巧](https://developers.cloudflare.com/workers/about/tips/debugging/#debug-tips) * [1.在try / catch中包装整个事件处理程序](https://developers.cloudflare.com/workers/about/tips/debugging/#1-wrap-your-whole-event-handler-in-a-try-catch) * [2.在标题中返回调试信息](https://developers.cloudflare.com/workers/about/tips/debugging/#2-return-debug-information-in-a-header) * [3.设置日志记录服务](https://developers.cloudflare.com/workers/about/tips/debugging/#3-setup-a-logging-service) * [4.出错时返回原点](https://developers.cloudflare.com/workers/about/tips/debugging/#4-go-to-origin-on-error) * [全部一起](https://developers.cloudflare.com/workers/about/tips/debugging/#all-together) ## 工作人员生成的错误页面 当生产环境中运行的Worker出现阻止返回响应的错误时,客户端将收到包含错误代码的错误页面,定义如下: | 错误代码 | 含义 | | --- | --- | | 1101 | Worker抛出了JavaScript异常。 | | 1102 | 工作者超过了CPU时间限制。请参阅:[资源限制](https://developers.cloudflare.com/workers/about/limits) | | 1015 | 您的客户端IP受到速率限制。 | | 1027 | 工人超出免费套餐[每日请求限制](https://developers.cloudflare.com/workers/about/limits#Daily-Request-Limit) | 其他11xx错误通常表示Workers运行时本身存在问题-如果看到错误,请检查我们的\[状态页面\](https://www.cloudflarestatus.com/)。 # 调试技巧 理想情况下,您可以使用或直接在[操场上](https://developers.cloudflare.com/workers/tooling/playground)编写和测试Worker`wrangler preview`。游乐场包含一个JavaScript控制台,您可以在其中查看调试信息,如`console.log()`s和未捕获的异常。希望您可以在推送之前使脚本完全在操场上工作。 但是,由于技术限制,游乐场并不总是能够完全生产出生产中会发生的事情。如果遇到在操场上看不到的问题,`console.log()`则不会在任何地方登录,并且未捕获的异常会产生一般错误页面(错误代码1101)。因此,我们建议您先将脚本部署到测试或“暂存”站点,然后再将其发布到实际站点中。您可以使用免费的[worker.dev](https://developers.cloudflare.com/workers/about/routes/#workers-dev)子域设置暂存环境。 我们正在努力改善这种体验,但是现在,这里有一些在现场站点调试的技巧: ### 1.在try / catch中包装整个事件处理程序 如果您从工作线程获取错误代码1101,则意味着它引发了异常。您可以使用常规old`try`/`catch`块在代码中捕获异常。(请注意,如果将代码分解为`async`函数,这将是最好的选择,否则,您还需要知道如何从promise中捕获异常。) ~~~javascript async function handleRequest(request) { try { ... some logic that might error .. return await fetch(newUrl, request) } catch (err) { // Return the error stack as the response return new Response(err.stack || err) } } ~~~ ### 2.在标题中返回调试信息 从您的Worker中获取一些调试信息的常见快速技巧是将其作为响应中的标头值返回。 ~~~javascript ... // Copy the response and initialize body to whatever info you want to log response = new Response(stack, response) // Shove our rewritten URL into a header to find out what it was. response.headers.set('X-Debug-stack', stack) response.headers.set('X-Debug-err', err) } return response } ~~~ ### 3.设置日志记录服务 工作者可以向公共互联网上的任何站点发出HTTP请求。许多项目已经具有类似[Sentry](https://sentry.io/)的服务,该服务可以从浏览器端JavaScript收集错误日志。通过向服务发出HTTP请求以报告错误,您可以使用同一服务从您的Worker收集错误。有关发出哪种请求的详细信息,请参阅服务的API文档。 使用此策略进行日志记录时,必须考虑以下事实:一旦Worker完成将其主要响应主体发送给客户端,就会取消未完成的异步任务。为了确保完成日志记录子请求,您可以将其`fetch()`承诺传递给[`event.waitUntil()`](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil)。例如: ~~~javascript ... // Without event.waitUntil(), our fetch() to our logging service may // or may not complete. event.waitUntil(postLog(stack)) return fetch(request) } function postLog(data) { return fetch('https://log-service.example.com/', { method: 'POST', body: data, }) } ~~~ ### 4.出错时返回原点 通常,如果您的工作人员没有执行对安全性至关重要的活动,则在出现错误时,使其看起来好像根本没有安装就有意义。这使您可以安装日志记录,跟踪或其他辅助工作者,而不必担心它们会破坏您的基础站点。可以通过调用`event.passThroughOnException()`以下行为来打开此行为: ~~~javascript addEventListener('fetch', event => { event.passThroughOnException() event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { // An error here will return the origin response, as if the Worker wasn’t present. ... return fetch(request) } ~~~ ### 全部一起 将上面的4个技巧放在一起,您将获得如下脚本: ~~~javascript const LOG_URL = 'https://log-service.example.com/' // Service set up to receive logs async function handleRequest(event) { let response try { response = await fetch(event.request) if (!response.ok) { let body = await response.text() throw new Error( 'Bad response at origin. Status: ' + response.status + ' Body: ' + body.trim().substring(0, 10), // ensures is string that can be a header ) } } catch (err) { // Without event.waitUntil(), our fetch() to our logging service may // or may not complete. event.waitUntil(postLog(err)) const stack = JSON.stringify(err.stack) || err // Copy the response and initialize body to the stack trace response = new Response(stack, response) // Shove our rewritten URL into a header to find out what it was. response.headers.set('X-Debug-stack', stack) response.headers.set('X-Debug-err', err) } return response } addEventListener('fetch', event => { // Have any uncaught errors thrown go directly to origin event.passThroughOnException() event.respondWith(handleRequest(event)) }) function postLog(data) { return fetch(LOG_URL, { method: 'POST', body: data, }) } ~~~