js单线程异步执行
- 执行栈(同步任务)
- 异步进程处理
- 任务队列
js典型的单线程执行机制,从前往后依次执行,所以当遇到定时器以及回调函数(异步任务)时,会先执行后面同步任务,当主线程(所有同步任务都执行完毕后再去任务队列中查看有没有任务,如果有,则执行代码)
异步任务
// 加载多个script时
function load(src,reslove){
var script=document.createElement('script');
script.src=src;
script.onload=resolve;
document.body.appendChild(script);
}
// 错误
// 异步加载是么有顺序的,取决于加载文件的快慢,如果是dd.js依赖于hd.js 有时候这个代码会出错,所以得用第二种
//load("../js/hd.js",()=>{
// hd();
//})
//load("../js/dd.js",()=>{
// dd();
//})
// 2...
// 代码不简洁
load("../js/hd.js",()=>{
load("../js/dd.js",()=>{
})
})
promise
// 准备 pending
console.log(new Promise((resolve,reject)=>{}));
//
console.log(new Promise((resolve,reject)=>{
resolve("接收状态");
}) )
//
console.log(new Promise((resolve,reject)=>{
reject("jujue状态");
}) )
// promise
// 微任务队列
// 微任务队列优先级高于宏任务
new Promise((resolve,reject)=>{
resolve("接收状态")
// reject("拒绝状态");
}).then(()=>{
console.log('success');
},()=>{
console.log('error');
})
js优先级
// 放到任务队列准备执行
// 宏任务队列
setTimeout(()=>{
console.log("计时器");
},delay)
// 发出成功通知也就是reslove就放入微任务队列
new Promise((resolve,reject)=>{
resolve("接收状态")
// **同步任务**
console.log("dd");
// reject("拒绝状态");
}).then(()=>{
console.log('success');
},()=>{
console.log('error');
})
//同步优先级最高
console.log('1');
上述代码的执行顺序是dd—>1 ------> success ------>计时器
// 改变场景
let promise=new Promise((resolve,reject)=>{
// **宏任务执行完毕后再去执行微任务*
// 轮询时先去微任务队列 没有 然后宏任务队列有
// 定时器,执行定时器碰到resolve,将微任
// 务放在微任务队列,再进行轮询
setTimeout(()=>{
console.log("111");
resolve("接收状态")
// console.log("111");
},delay)
console.log("dd");
// reject("拒绝状态");
}).then(()=>{
console.log('success');
},()=>{
console.log('error');
})
上述执行过程dd--------->111--------->success
let p1=new Promise((resolve,reject)=>{
// reject("拒绝");
setTimeout(()=>{
// 得到状态
reject("拒绝");
},2000)
});
new Promise((resolve,reject)=>{
// 等待2s得到状态
resolve(p1);
}).then(
msg=>{
console.log(msg);
},error=>{
console.log(error);
})
promise的状态是单向的,不可逆的,不能撤销
new Promise((resolve,reject)=>{
// 只会输出fullfilled
// 只要resolve微任务就被触发
resolve("fullfilled");
reject("拒绝");
}).then(
msg=>{
console.log(msg);
},error=>{
console.log(error);
})
例子
// p1.then() 也是一个promise对象
let p1=new Promise((resolve,reject)=>{
resolve("fullfilled");
});
console.log(p1);
let p2=p1.then(
value=>{
console.log(value);
},
error=>{
console.log(error);
}
)
console.log(p2);
修改一下
let p1=new Promise((resolve,reject)=>{
resolve("fullfilled");
});
let p2=p1.then(
value=>{
console.log(value);
},
error=>{
console.log(error);
}
)
// 宏任务
setTimeout(()=>{
console.log(p1);
console.log(p2);
})
因为任务栈中代码执行完毕后,先在微任务队列查找轮询,接着在宏任务中;所以将console放在定时器中时最后再执行,此时p1,p2都执行完毕了;
promise.then 链式
后面的then就是对前面返回的promise的处理,默认是成功状态;
new Promise((resolve,reject)=>{
resolve("fullfilled");
}).then(
value=>{
// 返回了一个promise
return new Promise((resolve,reject)=>{
// resolve("成功");
reject("shibai");
})
},
error=>{}
).then(
value=>{ console.log(value)},
error=>{console.log(error)}
)
上述是返回了一个promise,如果是返回一个对象呢,普通对象或者then
new Promise((resolve,reject)=>{
resolve("fullfilled");
}).then(
value=>{
return {
name:'dangdang'
}
},
error=>{}
).then(
value=>{ console.log(value)},
error=>{console.log(error)}
)
new Promise((resolve,reject)=>{
resolve("fullfilled");
}).then(
value=>{
return {
// 以下then可以被当做promise
then(resolve,reject){
reject("shibai");
}
}
},
error=>{}
).then(
value=>{ console.log(value)},
error=>{console.log(error)}
)
改写ajax回调为promise
function ajax(url,callback){
let xhr=new XMLHttpRequest();
xhr.open('GET',url);
xhr.send();
xhr.onload=function(){
if(this.status==200){
callback(JSON.parse(this.response));
}else{
throw new Error("加载失败");
}
}
}
function ajax(url){
return new Promise((resolve,reject)=>{
let xhr=new XMLHttpRequest();
xhr.open('GET',url);
xhr.send();
xhr.onload=function(){
if(this.status==200){
resolve(JSON.parse(this.response));
}
else{
reject("加载失败");
}
};
xhr.onerror=function(){
reject("加载失败");
}
})
}
//
<script src="../js/ajax.js"></script>
<script>
let url='...';
ajax(`${url}/...`).then(
value=>{console.log(value)},
error=>{console.log(error)}
)
</script>
// 实现请求user 和课程成绩
<script src="../js/ajax.js"></script>
<script>
let url='...';
ajax(`${url}/...name='username'`).then(
user=>{return ajax(`${url}/...id=${user.id}`)},
error=>{console.log(error)}
).then(
course=>{console.log(course)},
error=>{}
)
</script>