日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

自学JavaScript第四天- JS 进阶:AJAX Promise Canvas

發(fā)布時間:2024/3/24 javascript 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自学JavaScript第四天- JS 进阶:AJAX Promise Canvas 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

自學JavaScript第四天- JS 進階:AJAX Promise Canvas

  • AJAX
    • 使用 XMLHttpRequest
    • 使用 fetch() 方法
    • 處理 AJAX 數(shù)據(jù)
    • 安全限制
    • 跨域方案 CORS
      • 前端代碼
  • Promise 對象
    • 并行執(zhí)行異步任務(wù)
  • Canvas
    • 繪制形狀
    • 繪制文本
    • 其他

AJAX

使用 XMLHttpRequest

現(xiàn)代瀏覽器上寫AJAX主要依靠 XMLHttpRequest 對象

// 定義成功的回調(diào)函數(shù) function success(text) {var textarea = documnet.getElementById('test-response-text');textarea.value = text; } // 定義失敗的回調(diào)函數(shù) function fail(code) {var textarea = documnet.getElementById('test-response-text');textarea.value = 'Error code:' + code; } var request = new XMLHttpRequest(); // 新建 XMLHttpRequest 對象 // 狀態(tài)發(fā)生變化時,函數(shù)被回調(diào) // 也可以使用添加事件監(jiān)聽 request.addEventListener('readystatechange', () => {}) request.onreadystatechange = function() { if (request.readyState === 4) { // 成功完成// 判斷響應結(jié)果:if (request.status === 200) {// 成功,通過 responseText 拿到響應文本:return success(request.responseText);} else {// 失敗,根據(jù)響應碼判斷失敗原因:return fail(request.status);}} else {// HTTP 請求還在繼續(xù)} } // 建立發(fā)送的請求,true 表示異步發(fā)送 request.open('GET', '/api/categories', true); // 設(shè)置請求頭 request.setRequestHeader('Content-Type', 'application/json;charset=utf-8'); // 設(shè)置請求體(請求數(shù)據(jù)) let data = {'status':'ready'}; // 因為原生 ajax 發(fā)送的數(shù)據(jù)必須是字符串,所以需要序列化 data = JSON.stringify(data);// 發(fā)送請求,在此直線需要定義回調(diào)函數(shù) request.send(data);

當創(chuàng)建了 XMLHttpRequest 對象后,要先設(shè)置 onreadystatechange 的回調(diào)函數(shù)。在回調(diào)函數(shù)中,通常我們只需通過 readyState === 4 判斷請求是否完成(剛連接上服務(wù)器為 1 ,向服務(wù)器發(fā)送數(shù)據(jù)是 2,服務(wù)器傳送數(shù)據(jù)完成是 4),如果已完成,再根據(jù) status ===200 判斷是否是一個成功的響應。

XMLHttpRequest 對象的 open() 方法有3個參數(shù),第一個參數(shù)指定是 GET 還是 POST ,第二個參數(shù)指定URL地址,第三個參數(shù)指定是否使用異步,默認是 true ,所以不用寫。如果設(shè)置為同步,則瀏覽器會停止響應,呈現(xiàn)“假死”狀態(tài),直到 AJAX 請求完成。

最后調(diào)用 send() 方法才真正發(fā)送請求。 GET 請求不需要參數(shù), POST 請求需要把body部分以字符串或者 FormData 對象傳進去。

<input type='file' id='upload' onchange='upload(this.files[0])'><script>// 自定義 $ 函數(shù),獲取 dom 對象function $(domID) {return document.getElementById(domID)}function uploadImg(file) {// 判斷文件類型if (file.type.startsWith('image/')) {// 判斷文件大小if (file.size <= 1024 * 1024 * 2) {// 設(shè)置上傳地址let url = "/upload";let request = new XMLHttpRequest();// 創(chuàng)建監(jiān)聽事件request.onload = function (ev) {if (request.status === 200 && request.readyState === 4) {let respText = request.responseText;// 解析為 json 對象let respJson = JSON.parse(respText);console.log(respJson);}};// 創(chuàng)建上傳的數(shù)據(jù) form 對象let dataform = new FormData();// 添加字段和內(nèi)容dataform.append('photo', file);// 建立請求request.open('post', url, true);// 發(fā)送請求request.send(dataform)} else {// 文件大小超過限制alert('上傳的圖片大小在2M內(nèi)');}} else {// 文件類型超過限制alert('只能上傳圖片文件');}} </script>

使用 fetch() 方法

fetch() 是 XMLHttpRequest 的升級版,用于在 JavaScript 腳本里面發(fā)出 HTTP 請求。fetch() 的功能與 XMLHttpRequest 基本相同,但有三個主要的差異

  • fetch() 使用 Promise,不用回調(diào)函數(shù),簡化了寫法
  • 采用模塊化設(shè)計,API分散在多個對象上(Response、Request、Headers),使用更合理
  • fetch() 通過數(shù)據(jù)流(Stream對象)處理數(shù)據(jù),可以分塊讀取,有利于提高性能,減少內(nèi)存占用,適用于大文件或網(wǎng)速慢的場景
function login() {// 設(shè)置請求參數(shù)let option = {method: 'post', // 請求方法body: JSON.stringify({ // 請求體數(shù)據(jù)'name': '張三','pwd': '123456'}),headers: { 'Content-Type': 'application/json'}, // 請求頭數(shù)據(jù)mode: 'cors' // 請求模式,使用 cors 跨域(只在跨域時使用)};// 參數(shù)1是請求地址,參數(shù)2是請求參數(shù)fetch('http://text.io/login', option).then(response=>response.json()) // 執(zhí)行的是 resolve,即成功后的處理方法.catch(function (){// 執(zhí)行的 reject ,即失敗的處理方法}) }

處理 AJAX 數(shù)據(jù)

當 AJAX 拿到響應后,可以使用 request.responseText 獲取響應文本。如今大多數(shù)數(shù)據(jù)都是基于 JSON 格式的,所以要使用時也需要將響應文本解析成 JSON 對象。

let json = JSON.parse(request.responseText) // 將響應文本解析成為 JSON 對象

相應的,發(fā)送數(shù)據(jù)時,也需要將數(shù)據(jù)對象序列化為 JSON 對象才能發(fā)送

let json = JSON.stringify(obj);

安全限制

默認情況下,JavaScript在發(fā)送AJAX請求時,URL的域名必須和當前頁面完全一致。如果使用別的域名,則會報錯,這是因為瀏覽器的同源策略導致的。完全一致的意思是,域名要相同( www.example.com 和 example.com 不同),協(xié)議要相同( http 和 https 不同),端口號要相同(默認是 :80 端口,它和 :8080 就不同)。有的瀏覽器口子松一點,允許端口不同,大多數(shù)瀏覽器都會嚴格遵守這個限制。

使用 js 請求外域的URL,主要有四種方法

  • 通過 flash 插件,現(xiàn)在已經(jīng)被拋棄
  • 通過同源域名下的代理服務(wù)器轉(zhuǎn)發(fā)
  • 使用 JSONP,但是有個限制,只能使用 GET 請求,并且要求返回 JavaScript。
  • 如果瀏覽器支持 HTML5 ,可以使用新的跨域策略 CORS,這也是現(xiàn)在推薦使用的方式。

注:由于同源的安全策略是瀏覽器限制,所以請求的發(fā)送和響應是可以進行的,只是瀏覽器不接受罷了。另此策略不是對所有請求均制約,對 XmlHttpRequest 是制約的,對 img、iframe、script 等有 src 屬性的標簽不進行制約(所以這些標簽可以跨域使用)。

跨域方案 CORS

CORS全稱Cross-Origin Resource Sharing,是HTML5規(guī)范定義的如何跨域訪問資源。

Origin表示本域,也就是瀏覽器當前頁面的域。當JavaScript向外域發(fā)起請求后,瀏覽器收到響應后,首先檢查 Access-Control-Allow-Origin 是否包含本域,如果是,則此次跨域請求成功,如果不是,則請求失敗,JavaScript將無法獲取到響應的任何數(shù)據(jù)。

可見,跨域能否成功,取決于對方服務(wù)器是否愿意給你設(shè)置一個正確的 Access-Control-Allow-Origin ,決定權(quán)始終在對方手中。

上面這種跨域請求,稱之為“簡單請求”。簡單請求包括GET、HEAD和POST(POST的Content-Type類型 僅限 application/x-www-form-urlencoded 、 multipart/form-data 和 text/plain ),并且不能出現(xiàn)任何自定義頭(例如, X-Custom: 12345 ),通常能滿足90%的需求。

非簡單請求的跨域請求,需要進行預檢。PUT、DELETE以及其他類型如 application/json 的POST請求,在發(fā)送AJAX請求之前,瀏覽器會先發(fā)送一個 OPTIONS 請求(稱為preflighted請求)到這個URL上,詢問目標服務(wù)器是否接受,服務(wù)器必須響應并明確指出允許的Method,瀏覽器確認服務(wù)器響應的 Access-Control-Allow-Methods 頭確實包含將要發(fā)送的AJAX請求的Method,才會繼續(xù)發(fā)送AJAX,否則,拋出一個錯誤。除此外,還包括檢查是否符合 Access-Control-Allow-Headers 等設(shè)置的要求。

由于以 POST 、 PUT 方式傳送JSON格式的數(shù)據(jù)在REST中很常見,所以要跨域正確處理 POST 和 PUT 請求,服務(wù)器端必須正確響應 OPTIONS 請求。

前端代碼

前端使用 XMLHttpRequest 或 jQuery 沒有什么變化,正常發(fā)送 ajax 請求即可。對于簡單請求后端會添加 Access-Control-Allow-Origin ,然后返回數(shù)據(jù),瀏覽器檢查 Access-Control-Allow-Origin 并決定是否接受此響應。對于非簡單請求會自動發(fā)送 options 請求進行預檢,預檢完成后,發(fā)送負載請求。即所有工作在后端和瀏覽器進行。另外如果使用 fetch() 方法發(fā)送 ajax 請求,則注意需要在請求參數(shù)中添加 mode:'cors',表示使用 CORS 跨域請求。

Promise 對象

在JavaScript的世界中,所有代碼都是單線程執(zhí)行的。由于這個“缺陷”,導致JavaScript的所有網(wǎng)絡(luò)操作,瀏覽器事件,都必須是異步執(zhí)行。異步執(zhí)行可以用回調(diào)函數(shù)實現(xiàn)。異步操作會在將來某個時間觸發(fā)一個函數(shù)調(diào)用(回調(diào)),但是正常的寫法(例如AJAX)很不好看,而且不利于代碼復用,于是就出現(xiàn)了 Promise 對象。

Promise 會“承諾將來會執(zhí)行”回調(diào)函數(shù),Promise有各種開源實現(xiàn),在ES6中被統(tǒng)一規(guī)范,由瀏覽器直接支持。例如 AJAX 可以寫成

// ajax 函數(shù)將返回 Promise 對象: function ajax(method, url, data) {var request = new XMLHttpRequest();return new Promise(function (resolve, reject) {request.onreadystatechange = function() {if (request.readyState === 4) {if (request.status === 200) {resolve(request.responseText);} else {reject(request.status);}}};request.open(method, url);request.send(data);}); } // 調(diào)用 ajax var log = documnet.getElementById('test-promise-ajax-result'); var p = ajax('GET', '/api/categories'); p.then(function (text) { // 如果 ajax 成功,獲得響應內(nèi)容log.innerText = text; }).catch(function (status) { // 如果 ajax 失敗,獲得響應代碼log.innerText = 'ERROR:' + status; });

即,將一個異步函數(shù)作為參數(shù)構(gòu)建 Promise 對象,此函數(shù)有兩個參數(shù) resolve 和 reject,分別表示調(diào)用 成功 / 失敗的回調(diào)。那么 Promise 對象就可以通過 then 和 catch 方法調(diào)用相應的回調(diào)函數(shù)。

并行執(zhí)行異步任務(wù)

可以同時執(zhí)行多個異步任務(wù),并等待其執(zhí)行結(jié)果。使用 Pormise.all() 方法,并將需要執(zhí)行的 promise 任務(wù)對象放在數(shù)組中傳入即可。

// 同時執(zhí)行 p1 和 p2, 并在它們都完成后執(zhí)行 then: Promise.all([p1, p2]).then(function (results) {console.log(results); // 獲得一個各任務(wù)結(jié)果組成的 Array });

有時候,多個異步任務(wù)是為了容錯。比如,同時向兩個URL讀取用戶的個人信息,只需要獲得先返回的結(jié)果即可。這種情況下,用 Promise.race() 方法實現(xiàn),其他后返回的結(jié)果會被丟棄。

Canvas

Canvas是HTML5新增的組件,它就像一塊幕布,可以用JavaScript在上面繪制各種圖表、動畫等。沒有Canvas的年代,繪圖只能借助Flash插件實現(xiàn),頁面不得不用JavaScript和Flash進行交互。有了Canvas,我們就再也不需要Flash了,直接使用JavaScript完成繪制。

一個Canvas定義了一個指定尺寸的矩形框,在這個范圍內(nèi)我們可以隨意繪制:

<canvas id="test-canvas" width="300" height="200"></canvas>

由于瀏覽器對HTML5標準支持不一致,所以,通常在 <canvas> 內(nèi)部添加一些說明性HTML代碼,如果瀏覽器支持Canvas,它將忽略 <canvas> 內(nèi)部的HTML,如果瀏覽器不支持Canvas,它將顯示 <canvas> 內(nèi)部的HTML:

<!-- HTML代碼 --> <canvas id="test-canvas" width="200" heigth="100"><p>你的瀏覽器不支持Canvas</p> </canvas>

getContext('2d') 方法讓我們拿到一個 CanvasRenderingContext2D 對象,所有的繪圖操作都需要通過這個對象完成。

var ctx = canvas.getContext('2d');

如果需要繪制3D怎么辦?HTML5還有一個WebGL規(guī)范,允許在Canvas中繪制3D圖形:

gl = canvas.getContext("webgl");

繪制形狀

Canvas的坐標以左上角為原點,水平向右為X軸,垂直向下為Y軸,以像素為單位,所以每個點都是非負整數(shù)。CanvasRenderingContext2D 對象有若干方法來繪制圖形:

varcanvas = documnet.getElementById('test-canvas'),ctx = canvas.getContext('2d'); // 繪制形狀 ctx.clearRect(0, 0, 200, 200); // 擦除(0,0)位置大小為200x200的矩形,擦除的意思是把該區(qū)域變透明 ctx.fillStyle = '#dddddd'; // 設(shè)置顏色 ctx.fillRect(10, 10, 130, 130); // 把(10,10)位置大小為130x130的矩形涂色 // 利用Path繪制復雜路徑 var path = new Path2D(); // 繪制圓弧路徑,圓心坐標為(75,75),半徑為50,圓弧起點是0,終點的弧度是2倍的PI,逆時針繪畫 path.arc(75, 75, 50, 0, Math.PI*2, true); path.moveTo(110,75); path.arc(75, 75, 35, 0, Math.PI, false); ctx.strokeStyle = '#0000ff'; // 設(shè)置畫筆顏色 ctx.stroke(path); // 沿預設(shè)的路徑繪畫

繪制文本

繪制文本就是在指定的位置輸出文本,可以設(shè)置文本的字體、樣式、陰影等,與CSS完全一致

varcanvas = documnet.getElementById('test-canvas'),ctx = canvas.getContext('2d'); // 繪制文本 ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.shadowBlur = 2; ctx.shadowColor = '#666666'; ctx.font = '24px Arial'; ctx.fillStyle = '#333333'; ctx.fillText('帶陰影的文字', 20, 40);

其他

Canvas除了能繪制基本的形狀和文本,還可以實現(xiàn)動畫、縮放、各種濾鏡和像素轉(zhuǎn)換等高級操作。如果要實現(xiàn)非常復雜的操作,考慮以下優(yōu)化方案:

  • 通過創(chuàng)建一個不可見的Canvas來繪圖,然后將最終繪制結(jié)果復制到頁面的可見Canvas中;
  • 盡量使用整數(shù)坐標而不是浮點數(shù);
  • 可以創(chuàng)建多個重疊的Canvas繪制不同的層,而不是在一個Canvas中繪制非常復雜的圖;
  • 背景圖片如果不變可以直接用 <img> 標簽并放到最底層;

詳細的可以查看文檔

Canvas API 文檔

總結(jié)

以上是生活随笔為你收集整理的自学JavaScript第四天- JS 进阶:AJAX Promise Canvas的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。