- 什么是異步?
簡單的說就是先干一件事乳附, 中間去干其他的事,最終在回來干這件事。
- 每一個(gè)任務(wù)都有一個(gè)或者多個(gè)回調(diào)函數(shù)(callback)皮胡,前一個(gè)任務(wù)結(jié)束的時(shí)候,不是執(zhí)行下一個(gè)任務(wù)防嗡,而是執(zhí)行回調(diào)函數(shù)悼院,后一個(gè)任務(wù)則是不等前一個(gè)任務(wù)結(jié)束就執(zhí)行,所以程序的執(zhí)行順序與任務(wù)順序不一致的袱耽,異步的杀餐。
function read(content){
setTimeout(function(){
console.log(content)
} ,1000)
}
function read1(content){
setTimeout(function(){
console.log(content)
},500)
}
read('我是read');
read1('我是read1');
console.log('我先輸出') //第一個(gè)輸出的
read和read1執(zhí)行,read和read1的函數(shù)體中有setTimeout朱巨,它是異步的(異步不支持return)
- 同步:就是一個(gè)任務(wù)完成之后史翘,后邊跟著一個(gè)任務(wù)接著執(zhí)行;程序的執(zhí)行順序和排列順序是一直的(會(huì)阻塞代碼運(yùn)行)
- 異步的發(fā)展流程
1).callback:回調(diào)函數(shù)
let fs = require('fs');
fs.readFile('path', 'utf8', function (err, data) {
if (err) {
console.log(err)
}
if (data) {
fs.readFile(data, 'utf8', function (err, data) {
console.log(data);
});
}
})
會(huì)等第一個(gè)回調(diào)函數(shù)成功才會(huì)執(zhí)行第二個(gè)回調(diào)函數(shù)冀续。有多層嵌套的問題琼讽。代碼不好維護(hù)修改
2).promise: 解決了回調(diào)地獄的問題,不會(huì)導(dǎo)致難以維護(hù)
let fs = require('fs');
function read(path){
return new Promise(function(resolve,reject){
fs.readFile(path,'utf8',function(err,data){
if(err){
reject(err)
}else{
resolve(data)
}
})
})
}
let p = read('需要讀的文件路徑');
p.then((data)=>{
console.log(data);
})
3).Generator 函數(shù)
- 函數(shù)要用* 來標(biāo)識
- 返回結(jié)果是一個(gè)迭代器, 迭代器有一個(gè)next方法,調(diào)用next后都會(huì)返回一個(gè)done和一個(gè)叫value的屬性
原理:將一個(gè)函數(shù)劃分成若干個(gè)小函數(shù),沒次調(diào)用時(shí)移動(dòng)指針洪唐,內(nèi)部是一個(gè)條件判斷钻蹬,走對應(yīng)的邏輯
function read(arrs){
let index = 0; //默認(rèn)先迭代第一項(xiàng)
let len = arrs.length;
return {
next(){
return {value:arrs[index],done:index++===len?true:false}
}
}
}
let it = read(['react','vue','angular']);
// it.next(); // {done:false,value:'react'}
// it.next(); // {done:false,value:'vue'}
// it.next(); // {done:false,value:'angular'}
// it.next(); // {done:true,value:undefined}
缺點(diǎn):要手動(dòng)next執(zhí)行,才會(huì)進(jìn)行下一次
解決方案:co庫凭需,可以自動(dòng)的將generator進(jìn)行迭代
let bluebird = require('bluebird');
let fs = require('fs');
let read = bluebird.promisify(fs.readFile); //promise實(shí)例化
function* r() {
let content1 = yield read('./2.promise/1.txt', 'utf8');
let content2 = yield read(content1, 'utf8');
return content2;
}
co(r()).then(function (data) {
console.log(data)
})
4)async-await函數(shù)
- ES2017 標(biāo)準(zhǔn)引入了 async 函數(shù)问欠,使得異步操作變得更加方便肝匆。寫起來就就像同步函數(shù),而且有簡便的方式處理異步
- async 函數(shù)它其實(shí)就是 Generator 函數(shù)的語法糖溅潜。
let bluebird = require('bluebird');
let fs = require('fs');
let read = bluebird.promisify(fs.readFile);
// 用async 來修飾函數(shù)术唬,aysnc需要配await,await只能是promise
// async和await(語法糖) === co + generator
async function r(){
try{
let content1 = await read('./2.promise/100.txt','utf8');
let content2 = await read(content1,'utf8');
return content2;
}catch(e){ // 如果出錯(cuò)會(huì)catch
console.log('err',e)
}
}
// async函數(shù)返回的是promise,
r().then(function(data){
console.log(data);
},function(err){
})
async +await解決的問題:
- 回調(diào)地獄
- 并發(fā)執(zhí)行異步,在同一時(shí)刻同步返回結(jié)果 Promise.all
- 解決了返回值的問題
- 可以實(shí)現(xiàn)代碼的try/catch(同步才可以使用try/catch);