詳解JavaScript發(fā)送埋點請求的兩種方式
對于統(tǒng)計頁面數(shù)據(jù)這樣的情景(俗稱埋點),我們常用的方式就是動態(tài)創(chuàng)建<img>或<script>,至于原因,一般有以下幾點:
1.埋點一般不用關(guān)心請求的結(jié)果
2.可以實現(xiàn)跨域請求
3.無需使用ajax就能達到發(fā)請求的目的
4.都是原生實現(xiàn),兼容性好
現(xiàn)就兩種方式做一下對比和總結(jié):
一、用法
1.動態(tài)創(chuàng)建<img>
方式1:通過img標簽
function sendByImg(src) {
var img = document.createElement("img");
img.src = src;
}方式2:通過Image對象
function sendByImage(src) {
var img = new Image();
img.src = src;
}2.動態(tài)創(chuàng)建<script>
只有一種方式:通過<script>標簽
function sendByScript(src){
var script = document.createElement("script");
script.src = src;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(script);
}二、區(qū)別
區(qū)別1
如果要觸發(fā)請求,動態(tài)創(chuàng)建的<script>必須要插入到DOM中,而動態(tài)創(chuàng)建的<img>則不需要
演示代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Img VS Script</title>
</head>
<body>
<h3>
請觀察瀏覽器中的Network和Elements!
</h3>
<script>
function sendByScript(src){
var script = document.createElement("script");
script.src = src;
}
function sendByScriptInsertDOM(src){
var script = document.createElement("script");
script.src = src;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(script);
}
function sendByImage(src) {
var img = new Image();
img.src = src;
}
function sendByImg(src) {
var img = document.createElement("img");
img.src = src;
}
function sendRequest(src) {
//一、通過script:
//不插入DOM,不會觸發(fā)請求
sendByScript(src + '/byScript');
//插到DOM中,會觸發(fā)請求
sendByScriptInsertDOM(src + '/byScriptDOM');
//二、通過img:
//不插入DOM,不會觸發(fā)請求
sendByImage(src+ '/byImage');
//不插入DOM,不會觸發(fā)請求
sendByImg(src+ '/byImg');
}
sendRequest('https://wwww.baidu.com')
</script>
</body>
</html>用chrome瀏覽器打開此HTML文件,查看network:

可以看到,插入DOM中的<script>觸發(fā)來請求,而未插入DOM中則沒有發(fā)起請求;動態(tài)創(chuàng)建的<img>的兩種方式?jīng)]有插入DOM,都觸發(fā)請求。
那么問題來了,為什么動態(tài)創(chuàng)建的<script>必須要插入DOM中才會觸發(fā)請求,而動態(tài)創(chuàng)建的<img>則不用?關(guān)于這個問題,在網(wǎng)上查了很久也沒有找到特別強有力的解釋。有人說是因為這兩種標簽本身的特性決定的:<img>作為展示性標簽加載的是圖片資源,其對應(yīng)的地址可以直接訪問就能得到資源;<script>往往加載的是JavaScript代碼,需要網(wǎng)頁這樣的執(zhí)行環(huán)境。個人覺得此解釋有些牽強,但也沒有找到更權(quán)威的解釋。如果有更好的觀點,歡迎留言。
區(qū)別2
動態(tài)創(chuàng)建的<script>可以對請求結(jié)果進行處理,而動態(tài)創(chuàng)建的<img>做不到
JSONP的實現(xiàn)原理就是借助動態(tài)創(chuàng)建<script>標簽,并對返回結(jié)果進行處理。
至此,我當時在想,那么借助jQuery發(fā)送JSONP請求,豈不是每發(fā)一次就要在頁面上創(chuàng)建一個<script>標簽?觀察結(jié)果顯示并沒有。于是去看了下jQuery的源碼:

如圖所示,在<script>加載完成或出錯后將標簽移除。所以,我們在用動態(tài)創(chuàng)建<script>方式發(fā)送請求也可以參考這種方式。
三、選擇哪種方式
單純從發(fā)送請求的角度看,理論上兩者沒有特別大的差異,但有一點一定要注意:動態(tài)創(chuàng)建<img>的方式在瀏覽器禁用圖片模式下不會觸發(fā)請求。
例如,在chrome瀏覽器中設(shè)置禁圖模式(設(shè)置>高級設(shè)置>隱私設(shè)置和安全性>網(wǎng)站設(shè)置>圖片>顯示全部 去掉),結(jié)果:

只有動態(tài)創(chuàng)建<script>的方式有請求,動態(tài)創(chuàng)建<img>的方式?jīng)]有任何請求記錄。
綜上,從擴展性和兼容性上看,動態(tài)創(chuàng)建<script>的方式是首選。
四、總結(jié)
對于發(fā)送埋點請求這種應(yīng)用場景,我們有兩種簡單的處理方式:動態(tài)創(chuàng)建<script>和<img>兩種方式,兩者最大的差異是:動態(tài)創(chuàng)建的<script>必須插入到DOM中才能觸發(fā)請求,而動態(tài)創(chuàng)建<img>的方式則不需要。但動態(tài)創(chuàng)建<img>的方式有個致命缺陷:瀏覽器設(shè)置了禁止圖片顯示時,無法觸發(fā)請求。所以,對于封裝埋點庫的時候,動態(tài)創(chuàng)建<script>的方式是首選,而且可以參考jQuery,在請求記載完成后對<script>進行清除。
以上就是詳解JavaScript發(fā)送埋點請求的兩種方式的詳細內(nèi)容,更多關(guān)于JavaScript發(fā)送埋點的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
實現(xiàn)圖片首尾平滑輪播(JS原生方法—節(jié)流)
下面小編就為大家?guī)硪黄獙崿F(xiàn)圖片首尾平滑輪播(JS原生方法—節(jié)流)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
ES6使用export和import實現(xiàn)模塊化的方法
這篇文章主要介紹了ES6使用export和import實現(xiàn)模塊化的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09
深入理解Javascript中的循環(huán)優(yōu)化
這篇文章介紹了Javascript中的循環(huán)優(yōu)化,有需要的朋友可以參考一下2013-11-11
JavaScript實現(xiàn)將圖片地址轉(zhuǎn)成文件流并上傳
這篇文章主要為大家詳細介紹了如何使用JavaScript實現(xiàn)將圖片地址轉(zhuǎn)成文件流并上傳,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
JavaScript基礎(chǔ)篇(6)之函數(shù)表達式閉包
這篇文章主要介紹了javascript基礎(chǔ)篇(6)之函數(shù)表達式閉包的相關(guān)資料,需要的朋友可以參考下2015-12-12

