2022-11-25
res ajax
受javascript語言特性的影響,編程過程中充斥著大量異步回調,這會讓代碼維護起來特別麻煩,一步步走向回調地獄。社區中最早提出Promise解決方案,es6將其融入語法標準,并提供了generator、async,向類同步編程不斷努力。本文會通過這三個方面演示類同步進化過程。 ##1.Promise Promise提供異步編程的容器,包含異步代碼,在得到異步結果時,通過resolve傳遞數據(resove對應then所指定的函數,其實也就是單個過程的異步回調,可以理解成將之前的回調函數放在then方法中定義)。 ######以ajax請求封裝為例:
傳統形式
function ajax(url, success) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
//將請求結果作為實參傳入成功回調
success(xhr.responseText);
}
}
}
//如果兩個異步過程有先后順序,則會出現這種嵌套情況
ajax("http://vebcoder.cn:9527/api/getTypeOne", function (res) {
console.log(res);
ajax("http://vebcoder.cn:9527/api/goodList", function (res) {
console.log(res);
})
})
Promise形式
function ajax(url) {
//promise容器包裹異步過程
return new Promise(resolve => {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
//將異步結果使用resolve進行傳遞
resolve(xhr.responseText);
}
}
})
}
ajax("http://vebcoder.cn:9527/api/getTypeOne")
.then(res=>{
console.log(JSON.parse(res))
})
.then(()=>{
return ajax("http://vebcoder.cn:9527/api/goodList")
})
.then(res=>{
console.log(JSON.parse(res))
})
解決了回調函數橫向發展的問題,變成了縱向發展結構。直觀確實很直觀但是一大堆的then方法,!接下來generator登場
2.generator
乍一看,generator不過是一個有多個返回值的函數而已,奧妙在于如果不調用next方法,代碼會停止執行的。
基礎用法
//function后加*
function* Gen(){
console.log(1);
yield;
console.log(2)
yield;
console.log(3);
return;
}
//調用函數獲得指針對象
var g=Gen();
g.next();//1
g.next();//2
g.next();//3
第一次調用next執行到第一個yield,第三次執行到函數末尾return的位置。
奧妙之處
function* Gen(){
//用變量接收yield命令
var res=yield;
console.log(res)
}
var g=Gen();
g.next();
//next傳入參數
g.next(100);//100
第一次調用next方法,代碼執行到yield停止執行。第二次調用next傳入參數,代碼繼續執行,并將傳入next的參數賦值給res變量。next方法可以帶一個參數,該參數就會被當作上一個yield表達式的返回值。 那么我們就可以這樣做:
//上述封裝的ajax方法-傳統形式
function* Gen(){
//請求成功開始下一步
ajax("http://vebcoder.cn:9527/api/getTypeOne",res=>{g.next(res)})
// 接收yield返回值
let res=yield;
console.log(res)//請求的數據結果
}
var g=Gen();
// 開始執行代碼
g.next();
//上述封裝的ajax方法-Promise形式
function* Gen(){
//請求成功開始下一步
ajax("http://vebcoder.cn:9527/api/getTypeOne").then(res=>{g.next(res)})
// 接收yield返回值
let res=yield;
console.log(res)//請求的數據結果
}
var g=Gen();
// 開始執行代碼
g.next();
使用口訣:上一步回調,下一步,接收yield等待結果傳入
按理說這種形式已經不錯了,不用再往下看了,除非你能忍住!
3.async
async是generator的語法糖,你只需關注兩部、步操作就行。相當于對Promise和generator進行了融合。
async function Asy(){
//等待promise實例
let res=await ajax("http://vebcoder.cn:9527/api/getTypeOne")
console.log(res)//請求的數據結果
}
Asy();
//結合自執行函數
;(async function(){
let res=await ajax("http://vebcoder.cn:9527/api/getTypeOne")
console.log(res)//請求的數據結果
}())
async函數就是將Generator 函數的星號(*)替換成async,將yield替換成await。 注意:await后面需要跟一個promise實例,無需手動傳遞結果!
最后來一個對比(有次序的異步過程):
//傳統方式(對應上述傳統ajax封裝形式)
ajax("http://vebcoder.cn:9527/api/getTypeOne", function (res) {
console.log(res);
ajax("http://vebcoder.cn:9527/api/goodList", function (res) {
console.log(res);
})
})
//promise (對應上述promise ajax封裝形式)
ajax("http://vebcoder.cn:9527/api/getTypeOne")
.then(res=>{
console.log(JSON.parse(res))
})
.then(()=>{
return ajax("http://vebcoder.cn:9527/api/goodList")
})
.then(res=>{
console.log(JSON.parse(res))
})
//generator (對應上述promise ajax封裝形式)
function* Gen(){
//請求成功開始下一步
ajax("http://vebcoder.cn:9527/api/getTypeOne").then(res=>{g.next(res)})
// 接收yield返回值
let res=yield;
console.log(res);
ajax("http://vebcoder.cn:9527/api/goodList").then(res=>{g.next(res)})
// 接收yield返回值
let res2=yield;
console.log(res2);
}
var g=Gen();
// 開始執行代碼
g.next();
//async (對應上述promise ajax封裝形式)
// 發送請求
;(async function(){
let res=await ajax("http://vebcoder.cn:9527/api/getTypeOne")
console.log(res)//請求的數據結果
let res2=await ajax("http://vebcoder.cn:9527/api/goodList")
console.log(res2)//請求的數據結果
}())
async有更好的語義,幾乎達到與同步代碼一樣的編程體驗!
開班時間:2021-04-12(深圳)
開班盛況開班時間:2021-05-17(北京)
開班盛況開班時間:2021-03-22(杭州)
開班盛況開班時間:2021-04-26(北京)
開班盛況開班時間:2021-05-10(北京)
開班盛況開班時間:2021-02-22(北京)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2020-09-21(上海)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2019-07-22(北京)
開班盛況Copyright 2011-2023 北京千鋒互聯科技有限公司 .All Right 京ICP備12003911號-5 京公網安備 11010802035720號