Cloudflare Workers“单例”class

Cloudflare Workers “Singleton” class

我已经开始为我的网站使用工作人员。我网站上工作人员的目的: 主要是在 HTML 页面的不同位置注入一些代码(html/js/css)。 可以是一些配置数据,也可以是一些法律文本等

所以我现在要做的是在 KV 中为每个网站创建一个配置,并基于用户 country/language 在 html/js 之上注入等等

下面是一个 Store Class(单例模式),它保存了配置中的所有信息,但在 worker 中不起作用,by 不起作用 我的意思是,在第一次请求后,数据是持续存在,并在一段时间后更新:

例如第一个请求 URL:/about 在第二次请求 URL 时:/es/about/

通过输出 console.log(event.request) 将显示 /es/about ,但 Store.request 输出: /about/

任何解决此问题的方法,强制刷新数据,我想因为我不在构造函数中这样做,但通过调用自定义方法应该可以解决问题,但事实并非如此。?

下面是一些代码示例。


import { Store } from "@helpers/store";

addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request))
});

//HTML Rewriter Class
class Head {

    element(el) {
        el.append(`
                <script id="config">
                    var config = ${Store.export()};
                </script>`, {
            html: true
        });
    }
}

async function handleRequest(request) {
    let store = await Store.make(request);

    const response = await fetch(request);

    let html = new HTMLRewriter();
    html.on("head", new Head());

    return html.transform(response);
}

//src/helpers/store.js

class Store {

    constructor(){

        this._request = null
        this._config = {}
        this._url = null

    }

    async make(request){

        let config = {}

        this._request = request;

        const domain = this.url.hostname.replace(/www\./g, "");

        const country = request.headers.get('cf-ipcountry')

        const website = await WEBSITES.get(domain, "json"); //WEBSITES is KV namespace

        const { license, lang } = website;

        this._config = {
            country,
            domain,
            license,
            lang
        };

        return this;
    }

    export(){

        return JSON.stringify(this._config)
    }

    get request(){
        
        return this._request;

    }

    get url(){
        
        if(!this._url){

            this._url = new URL(this.request.url)

        }

        return this._url;

    }
}

export default new Store()

您的 Worker 的单个实例可以处理多个请求,包括并发请求。在您的代码中,您正在使用 Store 的单例实例来存储有关当前请求的元数据。但是如果并发处理多个请求,那么在第一个请求完成之前,第二个请求将覆盖 Store 的内容。这可能会导致第一个请求使用第二个请求的元数据呈现其 HTML。

您在这里似乎不希望使用单例模式。根据代码,您似乎真的想为每个请求创建一个单独的 Store 实例。

想到了 2 个问题:

  • 您正在为每次调用 worker 创建一个新的 HTMLRewriter。这将导致一些并发问题。重写器的实例化应该在 handleRequst 方法之外完成。例如在导入语句之后。
  • 您正在导入 Store class 并且从不实例化它,而是像它们是静态的(它们不是)一样使用它的方法。这也会给您带来并发问题。