本文介紹了三種型別的非同步網路請求:xmlhttprequest、promise 和 async await,其中 async await 允許我們以類似的方式編寫非同步程式,擺脫繁瑣的函式。
為了應對越來越多的測試需求,減少重複性工作,有道智慧型硬體測試集團開發了一系列基於電子的測試效率提公升工具。
隨著工具的快速發展和迭代,越來越多的巢狀函式被呈現出來,工具崩潰的概率也在增加。 為了解決這些問題,我們使用 async await 重構了這些函式結果,**的數量減少了,**的可讀性和可理解性大大提高。
本文介紹:有三種型別的非同步網路請求:xmlhttprequest、promise 和 async await其中 async await 表示法允許我們以類似於 Synchronively 的方式編寫非同步程式,從而擺脫繁瑣的函式。
在 JS 中,如果發出單個網路請求並不複雜,則可以使用 Fetch、Axios 或僅使用 xmlhttprequest。
但是,如果多個請求按順序拉取資料,編寫起來非常麻煩,因為 JS 中的網路請求是非同步的,需要按順序執行最常見的編寫方法是在 ** 函式中發出下乙個請求如下:
const requestoptions = )
catch(error => console.error('error', error));
catch(error => console.error('error', error));
假設我需要經歷兩個步驟來獲取一段資料,例如通過資料從資料中獲取資料物件id 獲取我想要獲取的資料的號碼,然後傳送另乙個請求來獲取我想要的資料。 **函式的使用方式與上述類似,過於繁瑣,容易出錯,一旦邏輯複雜,就不容易改變。
接下來,我們來梳理一下js的幾種網路請求方式,擺脫**地獄,希望能幫助到遇到類似問題的人。
第乙個是 xmlhttprequest,這是我第一次學習前端時著名的 ajax 所指的。 以下是通過 xmlhttprequest 物件建立網路請求的過程
假設訪問 http: localhost:3000 使用者返回乙個 JSON 物件。
const xhr = new xmlhttprequest();
const url = 'http://localhost:3000/user'
xhr.onreadystatechange = function()
xhr.open('get',url)
xhr.send()
本段首先建立乙個 xmlhttprequest 物件 xhr,然後給出 xhrOnReadyStateChange 為 ReadyStateChange 事件新增 ReadyStateChange 函式,後跟 xhropen('get', url) 初始化請求,最後通過 xhrsend() 傳送請求。
請求傳送後,程式繼續執行而不會阻塞,這也是非同步呼叫的好處。 當瀏覽器收到響應時,它會進入 xhronReadyStateChange。 在整個請求過程中,xhrOnReadyStateChange 被觸發四次,每次 ReadyState 都會從 1 到 4 自遞增,並且最終響應資料僅在 ReadyState 為 4 的最後階段可用。
到達第四階段後,還需要根據狀態判斷響應的狀態碼是否正常,通常響應碼為200,表示請求沒有遇到問題。 這個**最終會在主機上打有道。
可以看出,如果要通過 xmlhttprequest 處理請求,必須先為每個請求建立乙個 xmlhttprequest 物件,然後將 readystatechange 事件的 ** 函式繫結到每個物件。
Promise 是在 ECMAScript 2015 中引入的,如果乙個事件依賴於另乙個事件返回的結果,那麼使用它可能會很複雜。
promise 物件提供用於檢查操作失敗或成功的模式。 如果成功,則返回另乙個 promise。 這使得**的寫作更加規範。
以下是通過承諾處理它的方法:
const promise = new promise((resolve,reject)=> else
then( msg => console.log(msg))
catch( err => console.error(err))
finally( _=>console.log("finally"))
上面一段將整個過程串在一起,首先建立乙個promise物件,它的建構函式接收乙個函式,函式的第乙個引數是沒有錯誤時要執行的函式,第二個引數是錯誤後要執行的函式,r eject。
resolve 是指 then 中執行成功的 ** 函式,reject 是指執行失敗後 catch 中執行的 ** 函式。 無論成功還是失敗,最終都會執行,並且可用於對一些清理工作進行最後的潤色。
基於 Promise 的網路請求可以使用 Axios 庫或瀏覽器的本機提取來實現。
Axios 庫按如下方式建立請求:
import axios from 'axios'
const url = ''
axios.get(url)
then(data => console.log(data))
catch(err => console.error(err))
我更喜歡使用 fetch,fetch 是使用的瀏覽器 API 而不是 xmlhttprequest,它不需要庫,fetch 以類似於 axios 的方式建立請求,並且不會像開頭所示重複。
雖然 promise 簡化了函式的編寫方式,但它們仍然沒有擺脫地獄,如果將多個請求串在一起,那麼就會像我一開始寫的那樣建立乙個新的 promise,最終它會變成乙個 promise 地獄。
Async Await 是在 ECMASpoc 2017 中引入的,旨在簡化 promise 的編寫方式,使非同步函式呼叫按順序進行且易於理解。 讓我們使用開頭的例子:
使用 fetch 直接獲取資料:
const requestoptions = )
catch(error => console.error('error', error));
catch(error => console.error('error', error));
使用 async await 重寫後:
async function demo()
const response = await fetch('', requestoptions);
const data = await response.json()
const response1 = await fetch(''+data.id, requestoptions)
const data1 = await response1.json()
console.log(data1)
demo().catch(error => console.error('error',error))
改寫的**不是很清楚,沒有那麼多然後跟著,這樣如果有一系列的網路請求,就不用害怕了。
當 async 放在函式宣告之前時,該函式是乙個非同步函式,呼叫該函式將返回乙個 promise。 await 用於等待乙個 promise 物件,它只能在非同步函式中使用,await 表示式會暫停當前非同步函式的執行,等待 promise 處理完成。
這樣,如果想要按順序呼叫一系列非同步函式,可以簡單地將呼叫的函式放入乙個用非同步修飾的函式中,並在呼叫前新增 await,使這些函式順從地按順序執行。
通過對這篇文章的梳理,相信你已經知道該如何避免**地獄了。 但是需要注意的是,2015 年語言規範中新增了 promise,2017 年語言規範中新增了 async await,如果你的專案較舊或者必須與較舊的瀏覽器(如 IE6)相容,那麼你需要用另一種方式解決 **hell。
只要您使用的是近年來支援的 Electron 版本,就可以將 Electron 視為 Chromium 和 NodeJS 的組合,非常適合編寫跨平台實用程式桌面應用程式。