<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>

          一行代碼,把項(xiàng)目搞崩潰了!

          共 3494字,需瀏覽 7分鐘

           ·

          2024-05-15 13:48

          最近我們團(tuán)隊(duì)的同學(xué)在開(kāi)發(fā)中發(fā)生了一件 “有意思” 的事情,那就是通過(guò)一行代碼,讓網(wǎng)站卡死了,真的是離了大譜。團(tuán)隊(duì)同學(xué)寫(xiě)了一篇記錄,希望能長(zhǎng)個(gè)記性吧~

          背景

          今天下午,老魚(yú)簡(jiǎn)歷告警群里突然提示了幾個(gè)下載簡(jiǎn)歷失敗的提示。


          我看到后,心里一緊,趕緊打開(kāi)頁(yè)面看看我能不能下載,結(jié)果我這里下載是正常的。于是我就感覺(jué)事情不簡(jiǎn)單,趕緊本地啟動(dòng)項(xiàng)目調(diào)試,我本以為本地啟動(dòng)后控制臺(tái)會(huì)有報(bào)錯(cuò),但是實(shí)際上并沒(méi)有,沒(méi)辦法,只能使用絕招:二分法先定位到出問(wèn)題代碼。漫長(zhǎng)的縮短問(wèn)題代碼后,最后問(wèn)題代碼找到了

          /**
           * 判斷是否為鏈接
           * @param urlString 接受一個(gè)字符串
           * @returns 一個(gè) boolean 值,true 表示是鏈接,false 表示不是鏈接
           */

          export const isLink = (urlString: string) => {
            const regex = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
            return regex.test(urlString);
          };


          說(shuō)實(shí)話看到是因?yàn)檫@段代碼的我是這樣的:


          我本來(lái)是不會(huì)正則的,這個(gè)是 AI 幫我寫(xiě)的判斷鏈接的方法。我當(dāng)時(shí)就光測(cè)試它是否能判斷出一個(gè)字符串是否是鏈接,而忽略了特殊字符串是否會(huì)有性能問(wèn)題。最后,我給大家復(fù)現(xiàn)一下這個(gè)bug 最小代碼示例:

          /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/.test('https://www.suse.com/nbswebapp/createSummary.jsp?')


          只要你在游覽器控制臺(tái)輸入這個(gè),這個(gè)頁(yè)面立馬卡死。

          問(wèn)題原因分析

          那這是為什么呢?聽(tīng)聽(tīng)萬(wàn)能的 AI 這么說(shuō)的:在JavaScript中使用正則表達(dá)式時(shí),如果正則表達(dá)式的設(shè)計(jì)不當(dāng),特別是在處理復(fù)雜的字符串或者特定的模式時(shí),可能會(huì)導(dǎo)致性能問(wèn)題,甚至使瀏覽器卡死。這種現(xiàn)象通常稱(chēng)為“災(zāi)難性回溯”(Catastrophic Backtracking)。在你提供的正則表達(dá)式中:

          /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/


          這個(gè)表達(dá)式用于匹配URL,其中包含了幾個(gè)可選的組件和量詞(如*?),這些都可能導(dǎo)致正則表達(dá)式引擎進(jìn)行大量的回溯嘗試,尤其是當(dāng)輸入字符串在某些位置上與模式不匹配時(shí)。具體來(lái)說(shuō),問(wèn)題可能出現(xiàn)在([\/\w \.-]*)*這部分。這里使用了兩個(gè)嵌套的量詞(*外面還有一個(gè)*),這種嵌套的量詞是造成災(zāi)難性回溯的常見(jiàn)原因。當(dāng)輸入的URL在最后一部分(即[\/\w \.-]*應(yīng)該匹配的部分)稍有不符時(shí),正則表達(dá)式引擎可能會(huì)嘗試所有可能的分割方式來(lái)匹配整個(gè)模式,這會(huì)導(dǎo)致處理時(shí)間急劇增加。為了避免這種問(wèn)題,可以嘗試優(yōu)化正則表達(dá)式的結(jié)構(gòu),避免使用嵌套的量詞,或者使用更具體的字符類(lèi)匹配來(lái)減少潛在的回溯。例如,可以修改為:

          /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]+)?\/?$/


          這里,我將內(nèi)部的*修改為+,使得這部分至少匹配一次,減少了嵌套量詞的使用,這應(yīng)該可以幫助減輕瀏覽器的負(fù)擔(dān)。總之,設(shè)計(jì)正則表達(dá)式時(shí)需要注意避免復(fù)雜的嵌套和過(guò)度的通配符使用,特別是在處理可能非常長(zhǎng)或復(fù)雜的字符串時(shí)。這樣不僅可以避免瀏覽器卡死的問(wèn)題,還可以提高應(yīng)用的響應(yīng)速度和用戶(hù)體驗(yàn)。實(shí)測(cè),。這個(gè)正則是有問(wèn)題的:


          我現(xiàn)在是用新的檢測(cè)字符串是否是鏈接的方法,充足測(cè)試下來(lái)沒(méi)有問(wèn)題:

          /**
           * 判斷字符串是否為鏈接
           */

          export function isLink(urlString: string): boolean {
            const pattern = new RegExp(
              '^(https?:\\/\\/)?' + // 協(xié)議
                '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // 域名
                '((\\d{1,3}\\.){3}\\d{1,3}))' + // 或IP(v4)地址
                '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // 端口和路徑
                '(\\?[;&a-z\\d%_.~+=-]*)?' + // 查詢(xún)參數(shù)
                '(\\#[-a-z\\d_]*)?$',
              'i',
            ); // 錨點(diǎn)
            return !!pattern.test(urlString);
          }

          怎么避免?

          這次出現(xiàn)這個(gè)問(wèn)題的原因有兩個(gè)

          1. 經(jīng)驗(yàn)不足:如果我知道,不好的正則出導(dǎo)致災(zāi)難性回溯的話,我在拿到 AI 給我寫(xiě)的正則,我就會(huì)問(wèn)它給我的正則是否會(huì)導(dǎo)致災(zāi)難性回溯。
          2. 沒(méi)有充足的測(cè)試:如果我的項(xiàng)目有對(duì)這種工具方法的充足的測(cè)試,應(yīng)該也不會(huì)產(chǎn)生這個(gè) bug 了。

          總結(jié)

          遇到 bug 不要慌,從簡(jiǎn)單到難的使用排查問(wèn)題的方法。先定位到問(wèn)題。例如:我遇到bug,先定位前端問(wèn)題還是后端問(wèn)題,再定位問(wèn)題的大的位置,逐漸縮小范圍,最終找到問(wèn)題的位置。然后解決問(wèn)題。有沒(méi)有覺(jué)得這其實(shí)就是使用二分法的思想來(lái)定位問(wèn)題。找到問(wèn)題的代碼了,那其實(shí)就勝利一大半了,剩下的就是寫(xiě)出正確的代碼,做充足的測(cè)試,最后復(fù)盤(pán)這次 bug,以后不要再犯同樣的錯(cuò)就好了!



          ???? 點(diǎn)擊下方閱讀原文,獲取魚(yú)皮往期編程干貨。

          往期推薦

          我的編程學(xué)習(xí)小圈子

          我做了個(gè)網(wǎng)站,幫你寫(xiě)出滿(mǎn)分簡(jiǎn)歷

          我學(xué)計(jì)算機(jī)的四年,共勉

          雙非本,投遞4000+份簡(jiǎn)歷,上岸了!

          我開(kāi)源了一套 RPC 框架,學(xué)爆它!

          耗時(shí)幾個(gè)月,我們做的小工具上線啦!

          升級(jí)了項(xiàng)目的部署方式,坑死我了!

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          2點(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>
                  操比网站| 91人妻天天操天天干 | 亚洲最新视频在线免费播放不卡网站 | 免费看片av在线 免费毛片a在线看 | 伊人三级|