在 Cloudflare Worker 上响应后是否可以执行代码?
Is it possible to execute code after responding on a Cloudflare Worker?
我开始使用 Cloudflare 工作,我正面临第一个挑战。
我有一些缓存数据,一旦我通过 'fetch' 事件请求它,我就会检索这些数据。我想在响应此提取后,更新请求的缓存数据。
我从第三方获得这些数据 API。
工作流程如下。
- 获取请求并使用旧的缓存项进行响应
- 之后刷新所请求项目的缓存
我正在考虑使用 cron 计时器并填充要更新的项目队列,但我认为该列表不会持久化。
理想的方法是拥有某种自定义事件,我可以在 return 响应之前注册并触发,因此当我 return 更新旧缓存数据时,刷新缓存作业已经在执行。
我当前的代码正在运行(2 尚未实现),我不会发布代码,因为我只是想知道一些关于如何完成此刷新的理论。
提前致谢!
在 waitUntil
中做出承诺,然后 return 您的回应,有关详细信息,请参阅:https://developers.cloudflare.com/workers/runtime-apis/fetch-event#waituntil
如果您在服务工作者模式下部署了典型的工作者处理程序:
addEventListener("fetch", (event) => {
event.respondWith(
handleRequest(event).catch(
(err) => new Response(err.stack, { status: 500 })
)
);
});
并且在该函数中 handleRequest
您检查了是否已经有缓存的响应,如果没有则默认为虚拟响应
async function handleRequest(event) {
let response = await caches.default.match(event.request)
response = response ? new Response(response.body, response) : new Response('not found on cache ' + Date.now())
response.headers.set('response-datetime', new Date().toISOString())
return response
}
(为了这个例子,我正在从缓存的响应中创建一个新的、可修改的响应,如果有的话)
FetchEvent.waitUntil 是一种期望将 promise 作为参数的方法。您不需要等待 event.waitUntil
或其参数来解决。就像你做的一样
fetch(<url>).then(()=>console.log('fetch resolved'))
return response
或
setTimeout(()=>console.log('timeout callback'),500)
return response
之前的函数调用不会延迟响应。区别在于调用
event.waitUntil(getFreshInfoFromSomewhere(event.request))
将 worker 的生命周期延长到响应之后,直到它的 promise 参数被解析(当然,但仍然受到运行时时间限制)。
负责获取新响应的函数由您决定,我制作了一个将虚拟响应放入缓存中的函数,在请求后 500 毫秒:
/**
* @param {Request} request
* @returns {<Promise<void>>}
*/
function getFreshInfoFromSomewhere(request) {
return new Promise(resolve => {
let response = new Response('response-cached-on ' + new Date().toLocaleTimeString())
setTimeout(() => caches.default.put(request, response).then(resolve), 500)
})
}
/**
* @param {FetchEvent} event
* @returns <Promise<Response>>
*/
async function handleRequest(event) {
let response = await caches.default.match(event.request),
currentDatetime = new Date().toLocaleTimeString()
event.waitUntil(getFreshInfoFromSomewhere(event.request))
response = response ? new Response((await response.text()) + ', current datetime is ' + currentDatetime, response) : new Response('not found on cache at ' + currentDatetime)
response.headers.set('response-datetime', currentDatetime)
response.headers.set('cache-control', 'no-cache')
return response
}
addEventListener("fetch", (event) => {
event.respondWith(
handleRequest(event).catch(
(err) => new Response(err.stack, {
status: 500
})
)
);
});
您可以在 https://examples.ffflabs.com/cached
看到它正在运行
(这是一个非常低效的实现,我需要强调底层时间线)
我开始使用 Cloudflare 工作,我正面临第一个挑战。
我有一些缓存数据,一旦我通过 'fetch' 事件请求它,我就会检索这些数据。我想在响应此提取后,更新请求的缓存数据。
我从第三方获得这些数据 API。
工作流程如下。
- 获取请求并使用旧的缓存项进行响应
- 之后刷新所请求项目的缓存
我正在考虑使用 cron 计时器并填充要更新的项目队列,但我认为该列表不会持久化。
理想的方法是拥有某种自定义事件,我可以在 return 响应之前注册并触发,因此当我 return 更新旧缓存数据时,刷新缓存作业已经在执行。
我当前的代码正在运行(2 尚未实现),我不会发布代码,因为我只是想知道一些关于如何完成此刷新的理论。
提前致谢!
在 waitUntil
中做出承诺,然后 return 您的回应,有关详细信息,请参阅:https://developers.cloudflare.com/workers/runtime-apis/fetch-event#waituntil
如果您在服务工作者模式下部署了典型的工作者处理程序:
addEventListener("fetch", (event) => {
event.respondWith(
handleRequest(event).catch(
(err) => new Response(err.stack, { status: 500 })
)
);
});
并且在该函数中 handleRequest
您检查了是否已经有缓存的响应,如果没有则默认为虚拟响应
async function handleRequest(event) {
let response = await caches.default.match(event.request)
response = response ? new Response(response.body, response) : new Response('not found on cache ' + Date.now())
response.headers.set('response-datetime', new Date().toISOString())
return response
}
(为了这个例子,我正在从缓存的响应中创建一个新的、可修改的响应,如果有的话)
FetchEvent.waitUntil 是一种期望将 promise 作为参数的方法。您不需要等待 event.waitUntil
或其参数来解决。就像你做的一样
fetch(<url>).then(()=>console.log('fetch resolved'))
return response
或
setTimeout(()=>console.log('timeout callback'),500)
return response
之前的函数调用不会延迟响应。区别在于调用
event.waitUntil(getFreshInfoFromSomewhere(event.request))
将 worker 的生命周期延长到响应之后,直到它的 promise 参数被解析(当然,但仍然受到运行时时间限制)。
负责获取新响应的函数由您决定,我制作了一个将虚拟响应放入缓存中的函数,在请求后 500 毫秒:
/**
* @param {Request} request
* @returns {<Promise<void>>}
*/
function getFreshInfoFromSomewhere(request) {
return new Promise(resolve => {
let response = new Response('response-cached-on ' + new Date().toLocaleTimeString())
setTimeout(() => caches.default.put(request, response).then(resolve), 500)
})
}
/**
* @param {FetchEvent} event
* @returns <Promise<Response>>
*/
async function handleRequest(event) {
let response = await caches.default.match(event.request),
currentDatetime = new Date().toLocaleTimeString()
event.waitUntil(getFreshInfoFromSomewhere(event.request))
response = response ? new Response((await response.text()) + ', current datetime is ' + currentDatetime, response) : new Response('not found on cache at ' + currentDatetime)
response.headers.set('response-datetime', currentDatetime)
response.headers.set('cache-control', 'no-cache')
return response
}
addEventListener("fetch", (event) => {
event.respondWith(
handleRequest(event).catch(
(err) => new Response(err.stack, {
status: 500
})
)
);
});
您可以在 https://examples.ffflabs.com/cached
看到它正在运行(这是一个非常低效的实现,我需要强调底层时间线)