JavaScript因為是單線程的博脑,為了不阻塞線程,只能通過異步調(diào)用的形式票罐,今天學(xué)習(xí)了幾種異步編程的方法叉趣,特此記錄一下,因為之前有的地方也沒搞明白该押,現(xiàn)在算是搞的七七八八了疗杉。
-
回調(diào)函數(shù)
這種方法是JS中最古老的異步編程手段,最常見的就是原生的AJAX請求蚕礼,具體如下:
function success(result) {
console.log(result);
}
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState == 4) {
if(request.status == 200) {
success(request.response)
} else {
console.log(request.status);
}
} else {
}
};
request.open('GET', url, true);
request.send();
例子中的onreadystatechange就是一個回調(diào)函數(shù)烟具,請求狀態(tài)只要發(fā)生改變就會調(diào)用該函數(shù)。
-
Promise對象
傳統(tǒng)的異步調(diào)用如果嵌套的層次多了會造成代碼難以維護(hù)奠蹬,就比如上邊的例子朝聋,如果有請求相互依賴,就會使代碼橫向發(fā)展囤躁,很是繁瑣冀痕,不過可以通過Promise來使其結(jié)果和過程的代碼分離荔睹,實例如下:
function kiss(success, fail) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState == 4) {
if(request.status == 200) {
success(request.response)
} else {
fail(request.status);
}
} else {
}
};
request.open('GET', url, true);
request.send();
}
//創(chuàng)建一個Promise對象,需要傳遞一個函數(shù)金度,該函數(shù)包含兩個參數(shù)应媚,這兩個參數(shù)也都是函數(shù)
var pro = new Promise(kiss);
//當(dāng)在kiss內(nèi)部調(diào)用了success,就會被then捕捉到,如果調(diào)用的是fail就會被catch捕捉到
//Promise中文意思是承諾猜极,在該對象的理解上就是中姜,內(nèi)部的執(zhí)行結(jié)果只有兩種,
//一種是成功跟伏,一種是失敗丢胚,過程是不可更改的
pro.then(function(result) {
console.log(result);
})
.catch(function(error) {
console.log(error);
});
從這里可以看出來,把結(jié)果集中到了Promise對象上受扳,而其具體的執(zhí)行過程在另一個函數(shù)里面携龟。
-
Generator生成器
通過Promise對象實現(xiàn)的異步編程也不是很完美,因為如果過程多的情況下勘高,會出現(xiàn)多個then峡蟋,不能一目了然的知道每個then返回的具體是什么,那么可以使用生成器來實現(xiàn)異步編程华望,該方法是讓異步編程看起來更加的像同步編程蕊蝗,直接看例子:
function ajax(url) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState == 4) {
if(request.status == 200) {
myList.next(request.responseText); //3.進(jìn)入這個地方,把結(jié)果傳出去了赖舟,傳給的是上一個yield蓬戚,然后又開始執(zhí)行了
} else {
console.log(request.status);
}
} else {
}
};
request.open('GET', url, true);
request.send();
}
function* ajaxList() {
var result1 = yield ajax('http://api.jirengu.com/fm/getSong.php'); //2.啟動后執(zhí)行yield的函數(shù),然后暫停
console.log('這是第一個結(jié)果', result1);
var result2 = yield ajax('http://weixin.jirengu.com/weather/now?cityid=WX4FBXXFKE4F');
console.log('這是第二個結(jié)果', result2);
var result3 = yield ajax('http://api.jirengu.com/getWeather.php');
console.log('這是第三個結(jié)果', result3);
}
myList = ajaxList();
myList.next(); //1.啟動
Generator因為可以通過yield來記住執(zhí)行狀態(tài)宾抓,所以可以用來執(zhí)行異步編程子漩。
-
async/await
該方式跟生成器類似,不過更加的方便石洗,算是生成器的語法糖幢泼,具體注意地方已經(jīng)在實例中標(biāo)出,直接上例子:
function ajax1(url) {
return new Promise(function(success, failer) {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState == 4) {
if(request.status == 200) {
console.log('呵呵噠', request.responseText);
success(request.responseText);
} else {
console.log(request.status);
}
} else {
}
};
request.open('GET', url, true);
request.send();
});
}
async function asyncTest() {
var result1 = await ajax1('http://api.jirengu.com/fm/getSong.php');//await后面是一個promise對象讲衫,成功和失敗都會直接返回結(jié)果缕棵。
console.log(result1, '什么玩意啊1');
var result2 = await ajax1('http://weixin.jirengu.com/weather/now?cityid=WX4FBXXFKE4F');
console.log(result1, '什么玩意啊2');
}
var asyncPro = asyncTest();
console.log('這個是promise對象嗎?', asyncPro instanceof Promise);
具體在JS中常用的異步編程就以上幾種,其他的以后學(xué)習(xí)到了具體再做記錄焦人。