亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

詳解原生JavaScript實現jQuery中AJAX處理的方法

2019-11-20 10:06:42
字體:
來源:轉載
供稿:網友

在這篇文章,我使用 Node.js作為后端。沒錯,這就可以全棧(瀏覽器和服務器)JS了。Node.js 是很簡潔的,我鼓勵你能在 Github下載demo,并關注該項目。下面是服務器端的代碼:

// app.jsvar app = http.createServer(function(req, res){  if(req.url.indexOf("/scripts/") >= 0){    render(req.url.slice(1), "application/javascript", httpHandler);  } else if(req.headers['x-requested-with'] === 'XMLHttpRequest'){    // Send Ajax response  } else{    render('views/index.html', 'text/html', httpHandler);  }}

該代碼段通過檢測請求 URL,確定該app返回的相應內容。如果該請求來自 scripts 目錄,那么服務器將返回內容類型(content type)為 application/javascript 的相應文件。如果請求頭部的 x-requested-with 被設為 XMLHttpRequest,那么該請求是 Ajax 請求,然后返回相應數據。除了以上兩種情況,服務器將會返回 views/index.html。

下面我將會展開上一代碼段處理 Ajax 請求的注釋部分進行深入講解。在 Node.js端,我已處理了 render 和 httpHandler 的體力活:

// app.jsfunction render(path, contentType, fn) {  fs.readFile(__dirname + '/' + path, 'utf-8', function (err, str) {    fn(err, str, contentType);  });}var httpHandler = function (err, str, contentType) {  if (err) {    res.writeHead(500, {'Content-Type': 'text/plain'});    res.end('An error has occured: ' + err.message);  } else {    res.writeHead(200, {'Content-Type': contentType});    res.end(str);  }};


render 函數異步讀取被請求文件的內容。該函數向被作為回調函數的 httpHandler 傳遞一個引用。
httpHandler 函數檢測 error 對象是否存在(如:被請求文件不能被打開,該對象就會存在)。另外,指定類型是好的做法,那么服務器返回的文件內容就會擁有適當的 HTTP 狀態碼(status code)和內容類型(content type)。

測試 API
讓我們為后端API編寫一些單元測試,從而確保它們能正確運行。對于這類測試,我會請求 supertest 和 mocha幫助。

// test/app.request.jsit("responds with html", function(done){  request(app)    .get("/")    .expect("Content-Type", /html/)    .expect(200, done);});it('responds with javascript', function (done) {request(app)  .get('/scripts/index.js')  .expect('Content-Type', /javascript/)  .expect(200, done);});it('responds with json', function (done) {request(app)  .get('/')  .set('X-Requested-With', 'XMLHttpRequest')  .expect('Content-Type', /json/)  .expect(200, done);});

這些測試確保了我們的 app 對于不同請求能返回正確的內容類型(content type)和HTTP 狀態碼(status code)。一旦你安裝了這些依賴,那么你就能使用命令 npm test 運行這些測試。

界面
現在,讓我們看看用戶界面的 HTML 代碼:

// views/index.html<h1>Vanilla Ajax without jQuery</h1><button id="retrieve" data-url="/">Retrieve</button><p id="results"></p>

上述的 HTML 代碼看起來很簡潔。沒錯,正如你所看到的,所有令人興奮的事情都發生在 JavaScript。

onreadystate vs onload
如果你看過任何一本權威的、關于 Ajax 的書,你可能會發現 onreadystate 在書上隨處可見。該回調函數需要通過嵌套的 ifs 或多個 case 語句完成,這使得難以記憶。讓我們再次回顧 onreadystate 和 onload 事件。

(function() {  var retrieve = document.getElementById('retrieve'),    results = document.getElementById('results'),    toReadyStateDescription = function(state) {      switch (state) {        case 0:          return 'UNSENT';        case 1:          return 'OPENED';        case 2:          return 'HEADERS_RECEIVED';        case 3:          return 'LOADING';        case 4:          return 'DONE';        default:          return '';      }    };  retrieve.addEventListener('click', function(e) {    var oReq = new XMLHttpRequest();    oReq.onload = function() {      console.log('Inside the onload event');    };    oReq.onreadystatechange = function() {      console.log('Inside the onreadystatechange ev![此處輸入圖片的描述][1]ent with readyState: ' +        toReadyStateDescription(oReq.readyState));    };    oReq.open('GET', e.target.dataset.url, true);    oReq.send();  });}());

上述代碼會在 控制臺(console) 輸出以下語句:

2016510165104948.jpg (483×156)

onreadystatechange 事件能在請求的任何過程中被觸發。如能在每個請求前、請求末。但根據文檔,onload 事件只會在請求成功后觸發。又因為 onload 事件是一個常見的 API,所以你能在很短時間內掌握它。onreadystatechange 事件可作為后備(原文是backwards compatible 向后兼容?)方案。而 onload 事件應該是你的首選。而且 onload 事件與 jQuery 的 success 回調函數類似,難道不是嗎?

###設置請求頭部
jQuery 私下幫你設置請求頭部了,所以后端能檢測這是一個 Ajax 請求。一般來說,后端并不關心 GET 請求是從哪而來,只要能返回正確的響應即可。當你相用同樣的 web API 返回 Ajax 或 HTML 時,這就派上用場了。讓我們看看如何通過原生 JavaScript 設置請求頭部:

var oReq = new XMLHttpRequest();oReq.open('GET', e.target.dataset.url, true);oReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');oReq.send();

與此同時,我們在 Node.js 做一個檢測:


 

if (req.headers['x-requested-with'] === 'XMLHttpRequest') {  res.writeHead(200, {'Content-Type': 'application/json'});  res.end(JSON.stringify({message: 'Hello World!'}));}

正如你所看到的,原生 Ajax 是一個靈活且現代化的前端 API。你可以利用請求頭部做很多事情,其中一種是版本控制。例如,我想讓某個 web API 支持多個版本。但我又不想利用 URL,取而代之的是:通過設置請求頭部,使客戶端能選擇它們想要的版本。所以,我們能這樣設置請求頭部:

oReq.setRequestHeader('x-vanillaAjaxWithoutjQuery-version', '1.0');

然后,在后端寫上相應代碼:


 

if (req.headers['x-requested-with'] === 'XMLHttpRequest' &&  req.headers['x-vanillaajaxwithoutjquery-version'] === '1.0') {  // Send Ajax response}

我們能利用 Node.js 為我們提供的 headers 對象進行相應檢測。而唯一需要注意的地方是:以小寫字母讀取它們。

響應類型
你可能想知道為什么 responseText 返回的是字符串,而不是能被我們操作的普通 JSON(Plain Old JSON)。原來是因為我沒有設置合適的 responseType 屬性。該 Ajax 屬性會很好地告訴前端 API 所期望服務器返回的數據類型。所以,我們要好好利用它:

var oReq = new XMLHttpRequest();oReq.onload = function (e) {  results.innerHTML = e.target.response.message;};oReq.open('GET', e.target.dataset.url, true);oReq.responseType = 'json';oReq.send();

哇,這樣我們就不必再對返回的純文本解析為 JSON 了,我們能告訴 API 我們期待接收的數據類型。該特性幾乎得到了所有最新主流瀏覽器的支持。當然,jQuery 會自動幫我們轉為適當的類型。但現在的原生 JavaScript 也具有方便的、完成同樣事件的方法。 原生 Ajax 已經支持很多其它響應類型,如 XML。

但遺憾的是,到 IE11 為止,開發團隊仍未對 xhr.responseType='json' 進行支持。雖然該特性目前在 Microsoft Edge 得到支持。但這個 Bug 提出幾乎兩年了。我堅信 Microsoft 團隊一直在努力地改進瀏覽器。讓我們期待 Microsoft Edge、aka Project Spartan 當初提出的承諾。
當然,你可以這個解決這個 IE 問題:

oReq.onload = function (e) {  var xhr = e.target;  if (xhr.responseType === 'json') {    results.innerHTML = xhr.response.message;  } else {    results.innerHTML = JSON.parse(xhr.responseText).message;  }};

避免緩存
對 Ajax 請求進行緩存的瀏覽器特性都快被我們忘記了。例如,IE 就默認是這樣。我還曾因此導致我的 Ajax 不執行而苦惱了幾個小時。幸運的是,jQuery 默認清除瀏覽器緩存。當然,你能在純 Ajax 達到該目的,而且相當簡單:

var bustCache = '?' + new Date().getTime();oReq.open('GET', e.target.dataset.url + bustCache, true);

查看 jQuery 文檔,可知道 jQuery 在每個請求(GET)后面追加一個時間戳作為查詢字符串。這在某個程度上讓請求變得獨一無二,并避免瀏覽器緩存。每當你觸發 HTTP Ajax 請求,你能看到類似如下請求:

2016510165239133.jpg (323×145)

OK!這就沒有戲劇性的事情發生了。

總結
我希望你能喜歡這篇關于原生 Ajax 的文章。Ajax 在過去某段時間里,被人們看作是一種可怕的怪獸。而事實上,我們已經覆蓋了原生 Ajax 所有基礎知識。

最后,我會留給你一個簡潔的方式進行Ajax調用:

var oReq = new XMLHttpRequest();oReq.onload = function (e) {  results.innerHTML = e.target.response.message;};oReq.open('GET', e.target.dataset.url + '?' + new Date().getTime(), true);oReq.responseType = 'json';oReq.send();
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久亚洲国产精品| 国产国产精品人在线视| 欧美亚洲成人精品| 国产做受高潮69| 亚洲一区二区三区视频播放| 成人综合网网址| 欧美激情一区二区三区久久久| 91老司机精品视频| 成人激情视频免费在线| 黄网动漫久久久| 日韩精品在线看| 国内精品美女av在线播放| 亚洲国产一区二区三区四区| 日本免费一区二区三区视频观看| 精品福利在线视频| 国产一区二区成人| 欧美日韩在线观看视频小说| 欧美一区二区三区图| 欧美午夜激情小视频| 亚洲黄色在线观看| 欧美日在线观看| 久久国产精品电影| 高清在线视频日韩欧美| 538国产精品一区二区免费视频| 91高清免费在线观看| 日韩大片免费观看视频播放| 国产欧美精品日韩精品| 亚洲美女av网站| 中文字幕日韩高清| 亚洲欧洲美洲在线综合| 国产精品直播网红| 亚洲精品日韩欧美| 欧美国产日本高清在线| 中文字幕在线看视频国产欧美| 久久久久久久久国产| 亚洲一区二区三区在线免费观看| 日韩三级成人av网| 国产999精品久久久影片官网| 一区二区三区在线播放欧美| 欧美一级视频免费在线观看| 97超级碰碰碰久久久| 精品magnet| 亚洲一级免费视频| 亚洲欧美在线一区二区| 久久久久久久久综合| 上原亚衣av一区二区三区| 欧美xxxx做受欧美| 亚洲欧洲一区二区三区久久| 亚洲国产欧美一区二区三区久久| 色狠狠av一区二区三区香蕉蜜桃| 欧美一级成年大片在线观看| xxx一区二区| 国产精品黄页免费高清在线观看| www.99久久热国产日韩欧美.com| 欧洲亚洲免费在线| 国产第一区电影| 5566日本婷婷色中文字幕97| 欧美日韩国产中文精品字幕自在自线| 国内精品免费午夜毛片| 视频一区视频二区国产精品| 国产精品va在线播放| 久久精品小视频| 日韩欧美在线一区| 国产精品小说在线| 国产精品久久久久久av福利| 精品一区二区电影| 精品成人69xx.xyz| 国产在线日韩在线| 国产精品99久久久久久白浆小说| 久久久久久九九九| 国产激情久久久久| 欧美成人免费全部观看天天性色| 亚洲精品美女在线观看播放| 激情久久av一区av二区av三区| 日本a级片电影一区二区| 精品久久久久久久久久ntr影视| 国产精品久久一区| 亚洲丝袜在线视频| 欧美孕妇与黑人孕交| 亚洲午夜性刺激影院| 91视频8mav| 777国产偷窥盗摄精品视频| 国产精品久久久久久久久粉嫩av| 日韩中文字幕在线| 欧美乱人伦中文字幕在线| 91性高湖久久久久久久久_久久99| 欧美激情视频一区二区三区不卡| 伊人久久大香线蕉av一区二区| 亚洲人成电影网站色…| 国产精品一区电影| 91精品国产91久久久久久吃药| 中文字幕亚洲专区| 亚洲国产精品一区二区久| 亚洲精品98久久久久久中文字幕| 菠萝蜜影院一区二区免费| 欧美精品电影免费在线观看| 欧美最猛黑人xxxx黑人猛叫黄| 精品亚洲国产视频| 在线中文字幕日韩| 日韩亚洲欧美成人| 国产精品久久久久久av下载红粉| 久久久亚洲精品视频| 美女性感视频久久久| 日韩欧美中文字幕在线播放| 久久视频精品在线| 欧美电影免费观看网站| 国产午夜精品视频免费不卡69堂| 精品夜色国产国偷在线| 亚洲一区二区三区在线免费观看| 久久精品99久久久香蕉| 91美女片黄在线观| 亚洲成人精品在线| 91青草视频久久| 亚洲精品国产精品久久清纯直播| 8090成年在线看片午夜| 欧美在线观看日本一区| 在线观看免费高清视频97| 国产精品99导航| 91美女片黄在线观| 国产精品第三页| 亚洲精品综合久久中文字幕| 狠狠色噜噜狠狠狠狠97| 久久久女女女女999久久| 国产精品自拍偷拍| 欧美日韩在线影院| 夜夜嗨av一区二区三区四区| 日韩一级裸体免费视频| 成人高h视频在线| 国产精品久久久久久婷婷天堂| 国产亚洲精品一区二555| 色七七影院综合| 性日韩欧美在线视频| 欧美大奶子在线| 国产精品视频区| 欧美诱惑福利视频| 国产成人精品电影| 国产精品狠色婷| 中文字幕亚洲综合久久| 最近2019中文字幕第三页视频| 色爱精品视频一区| 日韩在线视频网站| 亚洲跨种族黑人xxx| 久久免费观看视频| 国产一区二区日韩| 国产精品久久久久久久av大片| 97激碰免费视频| 欧美自拍大量在线观看| 色黄久久久久久| 91社区国产高清| 狠狠色狠狠色综合日日五| 91精品免费看| 美女国内精品自产拍在线播放| 日韩午夜在线视频| 亚洲国产欧美久久| 青草青草久热精品视频在线观看| 亚洲国产成人av在线| 日韩国产欧美精品一区二区三区| 亚洲综合成人婷婷小说| 日韩av在线资源| 国产精品∨欧美精品v日韩精品| 久久久久免费视频| 午夜精品在线视频| 亚洲国产97在线精品一区| 3344国产精品免费看|