這次帶給大家原生JS怎麼非同步請求實作Ajax,原生JS非同步請求實作Ajax的注意事項有哪些,下面就是實戰案例,一起來看一下。
在前端頁面開發的過程中,經常使用到Ajax請求,非同步提交表單數據,或非同步刷新頁面。
一般來說,使用Jquery中的$.ajax,$.post,$.getJSON
,非常方便,但是有的時候,我們只因為需要ajax功能而引入Jquery比較不划算。
所以接下來便用原生JavaScrpit實作一個簡單的Ajax請求,並說明ajax請求中的跨網域存取問題,以及多個ajax請求的資料同步問題。
JavaScript實作Ajax非同步請求
簡單的ajax請求實作
Ajax請求的原則是建立XMLHttpRequest對象,使用這個物件來進行非同步傳送請求,具體實作參考下面程式碼:
function ajax(option) { // 创建一个 XMLHttpRequest 对象 var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"), requestData = option.data, requestUrl = option.url, requestMethod = option.method; // 如果是GET请求,需要将option中的参数拼接到URL后面 if ('POST' != requestMethod && requestData) { var query_string = ''; // 遍历option.data对象,构建GET查询参数 for(var item in requestData) { query_string += item + '=' + requestData[item] + '&'; } // 注意这儿拼接的时候,需要判断是否已经有 ? requestUrl.indexOf('?') > -1 ? requestUrl = requestUrl + '&' + query_string : requestUrl = requestUrl + '?' + query_string; // GET 请求参数放在URL中,将requestData置为空 requestData = null; } // ajax 请求成功之后的回调函数 xhr.onreadystatechange = function () { // readyState=4表示接受响应完毕 if (xhr.readyState == ("number" == typeof XMLHttpRequest.DONE ? XMLHttpRequest.DONE : 4)) { if (200 == xhr.status) { // 判断状态码 var response = xhr.response || xhr.responseText || {}; // 获取返回值 // if define success callback, call it, if response is string, convert it to json objcet console.log(response); option.success && option.success(response); // 调用成功的回调函数处理返回值 // 可以判断返回数据类型,对数据进行JSON解析或者XML解析 // option.success && option.success('string' == typeof response ? JSON.parse(response) : response); } else { // if define error callback, call it option.error && option.error(xhr, xhr.statusText); } } }; // 发送ajax请求 xhr.open(requestMethod, requestUrl, true); // 请求超时的回调 xhr.ontimeout = function () { option.timeout && option.timeout(xhr, xhr.statusText); }; // 定义超时时间 xhr.timeout = option.timeout || 0; // 设置响应头部,这儿默认设置为json格式,可以定义为其他格式,修改头部即可 xhr.setRequestHeader && xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8'); xhr.withCredentials = (option.xhrFields || {}).withCredentials; // 这儿主要用于发送POST请求的数据 xhr.send(requestData); }
上面的程式碼中有詳細的註釋,ajax的原理很簡單,總的來說就是使用XMLHttpRequest物件來傳送資料。這兒對這個對象進行補充說明。
程式碼中用了許多布林表達式的短路特性來取代條件語句的寫法,善用布林運算式的短路特性能讓大量簡單的條件語句簡化。 ^_^
# XMLHttpRequest物件的基本屬性
# readyState屬性有五個狀態值:
# 0:是uninitialized:未初始化。已經創建了XMLHttpRequest物件但是未初始化。
1:是loading:已經開始準備好要發送了。
2:是loaded,:已經發送,但是還沒有收到回應。
3:是interactive:正在接受回應,但還沒接收完。
4:是completed:接受回應完畢。
responseText:伺服器傳回的回應文字。只有當readyState>=3的時候才有值。當readyState=3,回傳的回應文字不完整,只有readyState=4,接收到完整的回應文字。 responseXML:回應資訊是xml,可以解析為Dom物件。 status:伺服器的Http狀態碼,若是200,則表示OK,404,表示為找不到。 statusText:伺服器http狀態碼的文字。如OK,Not Found。
XMLHttpRequest物件的基本方法
open(method,url,asyn):開啟XMLHttpRequest物件。其中method方法有get,post,delete,put。 url是請求資源的位址。第三個參數表示是否使用非同步。預設情況是true,因為Ajax的特徵就是非同步傳送。若使用同步則false。 send(body):發送請求Ajax。其中發送的內容可以是需要的參數,若是沒有參數,直接send(null)
使用方法
直接呼叫上面定義的ajax函數,傳送對應的選項和參數即可。
ajax({ url: '/post.php', data: { name: 'uusama', desc: 'smart' }, method: 'GET', success: function(ret) { console.log(ret); } });
跨域請求問題
# 使用ajax請求的時候,一定要注意一個問題:跨域請求。在沒有使用特殊手段的情況下,跨域請求:請求其他網域和連接埠下的URL資源的時候,會報 Access-Control-Allow-Origin 相關的錯誤。其主要原因是瀏覽器的同源策略限制,瀏覽器規定不能跨網域請求資源。
解決方法
下面簡單的提一下一些解決方案。在ajax頭部添加允許跨域請求的header,這種方式還需要服務端配合添加允許跨域請求的頭部才可以。下面是PHP新增允許POST請求跨域頭部的PHP範例:
// 指定允许其他域名访问 header('Access-Control-Allow-Origin:*'); // 响应类型 header('Access-Control-Allow-Methods:POST'); // 响应头设置 header('Access-Control-Allow-Headers:x-requested-with,content-type');
使用動態scrpit標籤,動態建立scrpit標籤並指向要求的位址的方法,也就是JSONP方式,需要在URL後面拼接一個回呼函數,標籤載入成功以後會呼叫回呼函數。
var url = "http://uusama.com", callbaclName = 'jsonpCallback'; script = document.createElement('script'); script.type = 'text/javascript'; script.src = url + (url.indexOf('?') > -1 ? '&' : '?') + 'callback=' + callbaclName; document.body.appendChild(script);
回呼函數需要設定為全域函數:
window['jsonpCallback'] = function jsonpCallback(ret) {}
多個ajax請求資料同步問題
單一ajax回傳資料非同步處理
#多个ajax请求互不相关,它们在被调用以后发送各自请求,请求成功以后调用自己的回调方法,互不影响。 因为ajax请求异步的特性,所有一些依赖于请求完成之后的操作我们都需要放在回调函数内部,否则的话,你在回调函数外面读取到的值是空。看下面的例子:
var result = null; ajax({ url: '/get.php?id=1', method: 'GET', success: function(ret) { result = ret; } }); console.log(result); // 输出 null
虽然我们在回调函数里面设置了result的值,但是在最后一行 console.log(result); 输出为空。 因为ajax请求是异步的,程序执行到最后一行的时候,请求并没有完成,值并没有来得及修改。 这儿我们应该把 console.log(result) 相关的处理,放在 success 回调函数中才可以。
多个ajax返回数据问题
如果有多个ajax请求,情况会变得有些复杂。 如果多个ajax请求是按照顺序执行的,其中一个完成之后,才能进行下一个,则可以把后面一个请求放在前一后请求的回调中。 比如有两个ajax请求,其中一个请求的数据依赖于另外一个,则可以在第一个请求的回调里面再进行ajax请求:
// 首先请求第一个ajax ajax({ url: '/get1.php?id=1', success: function(ret1) { // 第一个请求成功回调以后,再请求第二个 if (ret1) { ajax({ url: '/get2.php?id=4', success:function(ret2) { console.log(ret1); console.log(ret2) } }) } } }); // 也可以写成下面的形式 var ajax2 = function(ret1) { ajax({ url: '/get2.php?id=4', success:function(ret2) { console.log(ret1); console.log(ret2) } }); }; ajax({ url: '/get1.php?id=1', success: function(ret1) { if(ret1){ ajax2(ret1); } } });
如果不关心不同的ajax请求的顺序,而只是关心所有请求都完成,才能进行下一步。 一种方法是可以在每个请求完成以后都调用同一个回调函数,只有次数减少到0才执行下一步。
var count = 3, all_ret = []; // 调用3次 ajax({ url: '/get1.php?id=1', success:function(ret) { callback(ret); } }); ajax({ url: '/get2.php?id=1', success:function(ret) { callback(ret); } }); ajax({ url: '/get3.php?id=1', success:function(ret) { callback(ret); } }); function callback(ret) { if (count > 0) { count--; // 可以在这儿保存 ret 到全局变量 all_ret.push(ret); return; } else { // 调用三次以后 // todo console.log(ret); } }
另一种方法是设置一个定时任务去轮训是否所有ajax请求都完成,需要在每个ajax的成功回调中去设置一个标志。 这儿可以用是否获得值来判断,也可以设置标签来判断,用值来判断时,要注意设置的值和初始相同的情况。
var all_ret = { ret1: null, // 第一个ajax请求标识 ret2: null, // 第二个ajax请求标识 ret3: null, // 第三个ajax请求标识 }; ajax({ url: '/get1.php?id=1', success:function(ret) { all_ret['ret1'] = ret; // 设置第一个ajax请求完成,把结果更新 } }); ajax({ url: '/get2.php?id=1', success:function(ret) { all_ret['ret2'] = ret; // 设置第二个ajax请求完成,把结果更新 } }); ajax({ url: '/get3.php?id=1', success:function(ret) { all_ret['ret3'] = ret; // 设置第三个ajax请求完成,把结果更新 } }); var repeat = setInterval(function(){ // 循环检查是否所有设置的ajax请求结果的值是否都已被更改,都已被更改说明所有ajax请求都已完成 for(var item in all_ret) { if (all_ret[item] === null){ return; } } // todo, 到这儿所有ajax请求均已完成 clearInterval(repeat); }, 50);
PS:下面看下ajax异步请求实例代码,具体代码如下所示:
nbsp;html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <meta> <title>获得书籍列表</title> <script> var xmlhttp; var txt,x,xx,i; function loadXMLDoc(url,cfunc) { if(window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp = new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = cfunc; xmlhttp.open("GET", "<%=request.getContextPath()%>"+url, true); xmlhttp.send(); } function myFunction1() { loadXMLDoc("/xmls/books.xml",function(){ if(xmlhttp.readyState==4 && xmlhttp.status==200) { var xmlDoc = xmlhttp.responseXML; txt = ""; x = xmlDoc.getElementsByTagName_r("title"); for(i=0;i<x.length;i++) { txt = txt + x[i].childNodes[0].nodeValue+"<br/>"; } document.getElementByIdx_x("myp").innerHTML = txt; } }); } function myFunction2() { loadXMLDoc("/text/test1.txt",function(){ if(xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementByIdx_x("myp").innerHTML = xmlhttp.responseText; } }); } function myFunction3() { loadXMLDoc("/xmls/cd_catalog.xml",function(){ if(xmlhttp.readyState==4 && xmlhttp.status==200) { txt="<table border='1'><tr><th>Title<th>Artist" x= xmlhttp.responseXML.documentElement.getElementsByTagName_r("CD"); for(i=0;i<x.length;i++) { txt = txt + "<tr>"; xx = x[i].getElementsByTagName_r("TITLE"); { try{ txt = txt + "<td>" + xx[0].firstChild.nodeValue +""; } catch(er) { txt = txt +"<td>"; } xx = x[i].getElementsByTagName_r("ARTIST"); try { txt = txt + "<td>" + xx[0].firstChild.nodeValue +""; } catch(er) { txt = txt + "<td>"; } } txt = txt + "" } txt = txt + ""; document.getElementByIdx_x("myp").innerHTML =txt; } }); } </script> <h2 id="My-Book-Collection">My Book Collection:</h2> <button>获得我的图书收藏列表</button> <button>这是不同的请求</button> <button>获取CD信息</button> <p></p>
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上是原生JS怎麼非同步請求實作Ajax的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。