js的加载顺序
async 异步加载 如果没有异步加载,js加载的地址访问速度过慢,会一直同步等待,造成页面白屏
如果同步加载时,这个js中是不能获取body中任何dom元素,当使用异步时,因为异步时DOM树构建完成后执行的,所以可以调用body中的元素
defer 所有DOM加载完毕后调用 ,比async晚
<script src="./js/a.js" async defer></script>
<script src="./js/b.js" async></script>
数组中的匿名回调函数有哪些
var arr=[];
arr.forEach(function(){
})
arr.reduce(function(){
})
arr.sort(function(){
})
arr.every(function(){
})
...
setInterval(function(){
},1000)
setTimeout(function(){
},1000)
...
document.addEventListener("click",function(){
});
var img=new Image();
img.addEventListener("load",function(){
})
img.addEventListener("error",function(){
})
// 很多方法中都有回调函数
// 一种函数是直接执行回调函数,一种函数是触发执行
// 触发执行的函数中,又分为两种,一种是需要时间的,一种是触发即执行
// Promise主要应用于需要时间触发执行的回调函数
异步 同步
同步: 当前内容执行完毕后,再执行下面的内容
console.log("a");
document.addEventListener("aaa",fn2);
for(var i=0;i<3;i++){
console.log("b");
}
console.log("c");
fn();
var evt=new Event("aaa");
document.dispatchEvent(evt);
function fn(){
console.log("d");
fn1();
console.log("e")
}
function fn1(){
console.log("f")
}
function fn2(){
console.log("g")
}
异步执行:
// 不管是setTimeout还是setInterval设置0毫秒或者不设置都是默认1毫秒后执行
// 遇到需要时间触发的都叫做异步
// 先执行同步,当把所有的同步执行完成后的下一毫秒触发执行已经计算完成时间回调函数
console.log("a");
setTimeout(function(){
console.log("b");
},100)
for(var i=0;i<1000000000;i++){
}
console.log("c");
setTimeout(function(){
console.log("d");
},50)
异步执行:a,b的输出顺序
//==这样会1秒后同时打印a和b
setTimeout(function(){
console.log("a");
},1000)
setTimeout(function(){
console.log("b");
},1000)
//==1秒后先打印a,再过1秒后打印b,但是如果多的话就会造成回调地狱
setTimeout(function(){
console.log("a");
setTimeout(function(){
console.log("b");
},1000)
},1000);
// 1秒后先打印a,再过1秒后打印b,但是如果多的话就会造成回调地狱
setTimeout(fn,1000);
function fn(){
console.log("a");
setTimeout(fn1,1000);
}
function fn1(){
console.log("b");
}
setTimeout(fn,1000,"a");
function fn(n){
console.log(n);
if(n==="a") setTimeout(fn,1000,"b");
}
setTimeout(function(a){
console.log(a);
},1000,2)
//===输出10个20
for(var i=0;i<10;i++){
setTimeout(function(){
console.log(i)//10个20
});
}
i=20;
//===输出0-9
for(var i=0;i<10;i++){
setTimeout(function(i){
console.log(i)
},0,i);
}
异步之Promise
标准方法体
new Promise(function(resolve,reject){
// 在Promise中只能之前这两个参数中的任意一个,执行后将不会执行另外一个,并且只能执行一次
// 当执行resolve时,可以认为是成功了去执行的函数
// 当执行reject时,可以认为是失败了去执行的函数
resolve(1);//就会执行then中的第一个函数
reject(2);//就会执行then中的第二个函数
// 不管执行那个函数,都会传参,并且只能传一个参数
}).then(function(n){
console.log(n)
},function(m){
console.log(m)
})
Promise中有一个状态管理
1、默认状态是pending
2、当执行resolve函数,状态就会被改为fulfilled状态
3、当执行reject函数,状态就会被更改rejected状态
new Promise(function(resolve,reject){
resolve();//当执行resolve,执行then中的函数
reject();//当执行reject,执行catch中的函数
}).then(function(){
console.log("aa");
}).catch(function(){
console.log("bbb")
})
Promise.all()
// 将一个Promise组成的数组,放在Promise.all()中,
// 这时候就会按照这个数组的顺序,异步一个个将所有promise内容调用执行
// 最后将每个promise返回结果返回一个新数组中,通过执行then的函数带参传入
function loadImage(src){
return new Promise(function(resolve,reject){
var img=new Image();
img.src=src;
img.onload=function(){
resolve(img);
}
img.onerror=function(){
reject();
}
})
}
var arr=[];
for(var i=1;i<13;i++){
var p=loadImage(`./img/${i}.jpg`);
arr.push(p);
}
Promise.all(arr).then(function(list){
list.forEach(t=>console.log(t.src))
})
Promise.race() 谁先异步完成就在then的函数中带参返回
Promise.race(arr).then(function(img){
console.log(img);
})
async 函数
await
await 等待await后面的内容,前提条件是只能等待promise
await 返回的结果只能响应resolve返回的结果,如果可能调用reject,就会报错
如果可能调用reject时,就不能写直接赋值给变量,必须写成then和catch方式
await只能写在async函数,也就是说如果需要使用await时,它所有对应的函数就必须写成async
async函数使用return,不是函数执行后直接返回,async函数执行执行返回的是一个Promise
async函数使用return返回的结果必须使用then来获取
async function fn(){
var arr=[];
for(var i=1;i<15;i++){
// await 会等待loadImage函数中resolve调用的时候,
//并且把resolve中传出参数返回给await前面的变量
// 阻塞式异步
// var img=await loadImage(`./img/${i}.jpg`);
var img;
await loadImage(`./img/${i}.jpg`).then(function(img){
arr.push(img);
}).catch(function(){
})
}
return arr;
}
var p=fn();
console.log(p);
p.then(function(list){
console.log(list)
})
异步之微任务与宏任务
宏任务将会新建一个新的任务列,并且放在这个新任务列的最前面
微任务将会把当前任务放在当前任务列的最下面
setTimeout setInterval 宏任务
Promise中then和catch里面的函数中执行就是微任务 async函数中await也是微任务
console.log("a");
Promise.resolve().then(function(){
console.log("b");
})
console.log("c");
new Promise(function(resolve,reject){
resolve();
console.log("e")
}).then(function(){
console.log("d")
})
//======输出 a c e b d
new Promise(function(resolve,reject){
resolve();
}).then(function(){
console.log("a")
return new Promise(function(resolve,reject){
resolve();
})
}).then(function(){
console.log("b")
return new Promise(function(resolve,reject){
resolve();
})
}).then(function(){
console.log("c")
return new Promise(function(resolve,reject){
resolve();
})
}).then(function(){
console.log("d")
});
Promise.resolve().then(function(){
console.log("a1");
Promise.resolve().then(function(){
console.log("b1");
Promise.resolve().then(function(){
console.log("c1");
Promise.resolve().then(function(){
console.log("d1");
})
})
})
})
//===输出 a a1 b1 c1 b d1 c d
console.log(1);
new Promise(function(resolve,reject){
console.log(2);
resolve();
}).then(function(){
console.log(3);
})
Promise.resolve().then(function(){
console.log(4);
})
setTimeout(function(){
console.log(5);
})
Promise.resolve().then(function(){
setTimeout(function(){
console.log(6);
})
})
console.log(7);
//===输出 1 2 7 3 4 5 6