一个你从来没有见过的window变量

什么,我难道不认识window变量嘛?在我有限的前端职业生涯中,每天都和window变量相爱相杀,为什么和我说这个。

可是你有见过Node.js中的window变量么

TSW中的window变量

TSW是什么

TSW(Tencent Server Web)是一套面向WEB前端开发者,以提升问题定位效率为初衷,提供染色抓包、全息日志和异常发现的Node.js基础设施。

TSW中的window是什么

正如我们所熟悉的浏览器中的window对象广义上代表一个页面的生命周期,在TSW中window对象代表了一个请求的生命周期。
那么window对象的价值到底在哪里?

在浏览器里,想要cookie的时候通过上下文window变量就取到了,从来没有觉得取cookie是一件特别费劲的事。但到Node.js里就不同了,对于取cookie这么简单的需求,需要特别关注request对象在哪里。因为request对象是局部变量,无法全局获得,这就是问题的本质。
直到2014年,一种实现上下文的方法被发现,window对象诞生。利用process.domain总是指向当前包裹自己的domain对象这一个特性来完成上下文自动切换。
window对象的本质是与request对象生命周期绑定的全局变量。你可以在任何时候通过window获取request对象,进而取得cookie等其它信息。
window的出现,打通了不同维度间的联系,把这些联系落地,就可以产生新的价值。
比如在DNS解析API中,是没有用户概念的,用户存在于更高维度中,高维对低维不可见,通过window对象,低维度里可以知道正在为哪个用户做解析服务。当解析结果有问题时,知道影响了哪个用户,通过用户也能回朔到解析过程。

它默认被挂载在global上,global.window,其中主要包含了如下一些内容:

    global.window = {
        disable () {}, // 禁止在global上挂载window对象
        enable () {}, // 启用global上的window对象,默认是启用的
        request: {}, // 请求对象
        response: {}, // 响应对象
        websocket: {} // websocket对象
    }

这样我们就能轻易地引用到请求的上下文对象了。一切都看起来非常顺利、美好和方便。
但是有一天,我用了引入了Vue SSR,服务器端给了一行报错:
TypeError: Cannot read property 'userAgent' of undefined
机智的我迅速去看了下报错对应的代码,找到了Vue的源代码。发现有一个对浏览器环境判断失准的问题,Vue会判断当前是在browser端还是在node端,代码是这么写的:

    // 检查是否在浏览器环境中
    const inBrowser = typeof window !== 'undefined'
    // 获取UA,这行会报错
    const UA = inBrowser && window.navigator.userAgent.toLowerCase()

那作为开发者的我就尴尬了,这样的判断确实在大多数场景下没有问题,遵循约定俗成的约定来说,这种直接了当的方式可以解决。但是在更为复杂的环境中,比如node端模拟了window变量,就撂挑子不干了。
这个时候我当然可以选择通过window.disable()来禁用掉global上的window对象,但这让我牺牲了一些便捷性。
到底有没有更好的解决方法呢?
判断环境的代码可不可以更加精准和精致呢?

世上原本到处都是路,一条路走的人多了,有更好风景的路就被埋没了。

    const inBrowser = (() => {
        try {
            return this === window
        } catch(e) {
            return false
        }
    })()

如果我来写的话,可能会用这个。

Comments
Write a Comment