<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          社區(qū)精選|腳本執(zhí)行順序引發(fā)的慘案

          共 6701字,需瀏覽 14分鐘

           ·

          2023-09-08 03:01

          今天小編為大家?guī)淼氖巧鐓^(qū)作者 記得要微笑 的文章,讓我們一起來看看這場(chǎng)腳本執(zhí)行順序引發(fā)的慘案??




          ▏歲月磨我少年志,時(shí)光涼我善良心。人間總有一絲情,抵我心中意難平。

          在某個(gè)工作日,有線上用戶向客服專員反饋稱無法正常訪問"查看報(bào)價(jià)頁面",頁面內(nèi)容無法呈現(xiàn),且問題表現(xiàn)時(shí)好時(shí)壞。客服專員收到反饋后,將問題轉(zhuǎn)交給SRE(系統(tǒng)可靠性工程師)進(jìn)行處理。令人困惑的是,SRE在訪問生產(chǎn)環(huán)境的"查看報(bào)價(jià)頁面"時(shí)發(fā)現(xiàn)一切正常。

          為了進(jìn)一步分析和定位問題,SRE向用戶申請(qǐng)了遠(yuǎn)程操作權(quán)限。在遠(yuǎn)程操作期間,并沒有發(fā)現(xiàn)瀏覽器控制臺(tái)中存在錯(cuò)誤日志,所有頁面所依賴的JavaScriptCSS腳本都能夠正常加載,但加載完成后并沒有執(zhí)行掛載頁面模塊的操作。因此,初步猜測(cè)問題可能出現(xiàn)在頁面路由加載方面,導(dǎo)致頁面無法正常掛載。

          以下是使用react-router模塊進(jìn)行路由配置的部分代碼,同時(shí)在路由加載過程中進(jìn)行數(shù)據(jù)采集:

          component: Loadable({    loader: () => import('@/pages/inquiry-detail-by-brand').then((comp) => {        /** 頁面訪問 PV、UV */        debugger;        if ('cassSensorsTrack' in window) {            (window as any).cassSensorsTrack({                eventName: BURY_EVENT_NAME.QUOTATION_RESULT_PAGE_VIEW_CLICK,                desc: '頁面瀏覽',                eventType: 'click',                eventData: '',            });        }        return comp;    }),    loading: Loading,})


          懷疑頁面組件模塊comp沒有正確掛載到頁面上,在then回調(diào)函數(shù)中添加斷點(diǎn)來驗(yàn)證自己的猜想。



          經(jīng)過調(diào)試,發(fā)現(xiàn)問題是在腳本執(zhí)行時(shí),cassSensors 對(duì)象未定義,導(dǎo)致無法調(diào)用 track 方法。此外,外部代碼沒有包含異常處理的 try...catch 塊。然而,在使用 Loadable 組件時(shí),它內(nèi)部捕獲了該異常,并渲染了空內(nèi)容。



          // 加載函數(shù)function load(loader) {  var promise = loader();
          var state = { loading: true, loaded: null, error: null };
          state.promise = promise.then(function (loaded) { state.loading = false; state.loaded = loaded; return loaded; }).catch(function (err) { // 捕獲異常 state.loading = false; state.error = err; throw err;  });
          return state;}
          // renderLoadableComponent.prototype.render = function render() { if (this.state.loading || this.state.error) { return React.createElement(opts.loading, { isLoading: this.state.loading, pastDelay: this.state.pastDelay, timedOut: this.state.timedOut, error: this.state.error, retry: this.retry }); } else if (this.state.loaded) { return opts.render(this.state.loaded, this.props); } else { return null; }};

          為什么在加載頁面組件腳本后獲取不到 cassSensors 變量呢?


          注:上述腳本加載順序是模擬出來的場(chǎng)景,跟實(shí)際腳本加載順序一致


          不難發(fā)現(xiàn)問題是由于:

          3.72881c2b.chunk.js 和 4.e6995327.chunk.js 在 sensorsdata1.19.4.min.js 之前加載和執(zhí)行,導(dǎo)致在執(zhí)行 .then 回調(diào)時(shí)無法訪問到 cassSensors 變量。


          這是因?yàn)椋?/span>

          cassSensors 是由 sensorsdata1.19.4.min.js 在全局作用域中注入的,而在回調(diào)執(zhí)行時(shí)它尚未定義,從而導(dǎo)致異常。



          異步加載腳本執(zhí)行順序是無法預(yù)估的,要確保頁面腳本能夠正確獲取到全局變量cassSensors,可以采用以下優(yōu)化方案。在異步加載完成之前,先給出一個(gè)結(jié)構(gòu)變量定義,讓應(yīng)用方調(diào)用不會(huì)報(bào)錯(cuò)。同時(shí),可以在頁面腳本中創(chuàng)建一個(gè)變量來緩存需要采集的數(shù)據(jù),等待腳本加載完成后再進(jìn)行上報(bào)操作。

          // cassSensors.jsvar dataCache = [];
          // 在異步腳本腳本完之前先給出結(jié)構(gòu)變量定義,讓調(diào)用方不會(huì)執(zhí)行報(bào)錯(cuò)if (!"cassSensors" in window) { window.cassSensors = { track: function() {}, // ... }}// 異步腳本加載完成后,重新拋出變量,并且上報(bào)緩存中的數(shù)據(jù)script.onload = fucntion() { window.cassSensors = window['sensorsDataAnalytic201505']; window.cassSensors.init(); // ... if (dataCache.length) { dataCache.forEach(function(dc) { window.cassSensors.track(dc); // 上報(bào) }); dataCache = []; }}

          通過這種優(yōu)化方式,即使在異步加載未完成之前,給出了一個(gè)結(jié)構(gòu)變量定義,應(yīng)用方可以正常調(diào)用cassSensors,避免了報(bào)錯(cuò)。同時(shí),通過緩存數(shù)據(jù)并在加載完成后進(jìn)行上報(bào),確保頁面腳本能夠正確獲取到cassSensors變量,并且不會(huì)因?yàn)榧虞d順序問題而導(dǎo)致異常。

          在封裝腳本時(shí),向全局作用域注入變量并不是最優(yōu)的方式。這種方式存在一些問題,如變量命名沖突、腳本執(zhí)行依賴順序?qū)е芦@取不到變量、重復(fù)引入腳本導(dǎo)致重復(fù)注入(單例模式)等。為了更加優(yōu)雅地封裝腳本并解決這些問題,推薦使用npm包的形式進(jìn)行發(fā)版、按需引入和構(gòu)建打包到業(yè)務(wù)代碼中。

          另外,上述線上問題是一個(gè)很小概率且難以復(fù)現(xiàn)的問題,遇到此類問題時(shí),您可以考慮使用 Fiddler 反向代理來延遲加載 sensorsdata1.19.4.min.js 文件,以使頁面腳本的執(zhí)行在 sensorsdata1.19.4.min.js 之前。

          沒有 Fiddler 破解版的同學(xué)可以使用 Nginx 來模擬該場(chǎng)景,并通過第三方的 echo-nginx-module 模塊進(jìn)行配置,以實(shí)現(xiàn)延遲響應(yīng)的反向代理。具體安裝步驟可以參考:https://www.cnblogs.com/52fhy/p/10166333.html

          配置反向代理示例:
          http {  listen       8081;  server_name  localhost;  # 其他配置項(xiàng)...    server {    # 其他 server 配置項(xiàng)...    location /proxy/ {        rewrite ^/proxy/(.*)$ /$1 break;        proxy_pass https://mstatic.cassmall.com;        # 設(shè)置頭部內(nèi)容編碼類型,防止返回亂碼        proxy_set_header Accept-Encoding "";        proxy_set_header Accept-Language $http_accept_language;        proxy_set_header Content-Type "text/javascript; charset=utf-8";    }
          location /delay { # prelight request if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } # 設(shè)置反向代理目標(biāo)服務(wù)器 # proxy_pass http://your_backend_server;      echo_location /proxy/$uri;
          # 設(shè)置延遲時(shí)間為 5 秒鐘 set $delay 5; # 在代理響應(yīng)之前延遲 5 秒鐘 echo_sleep $delay; } }}

          echo_sleep 與 proxy_pass 配置會(huì)有沖突,兩者同時(shí)配置,只有一個(gè)會(huì)生效,所以此處使用 echo_location。




          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動(dòng)和交流,公眾號(hào)后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -



          往期推薦



          社區(qū)精選|“奇怪”的 Axios 攔截器


          社區(qū)精選|納尼!CSS 也能實(shí)現(xiàn)碰撞檢測(cè)?


          社區(qū)精選|【NestJS 系列】DI 依賴注入與 IOC 控制反轉(zhuǎn)

          瀏覽 348
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  男女拍拍免费 | 免费亚洲婷婷 | 小泬BBBB免费看 | 亚洲一级一片 | 欧美a日韩 |