异步编程
因为JavaScript是单线程工作,只有一个任务执行完成后才能执行下一个任务,两个任务不能同时执行,如果某个任务耗时很长(比如读取一个大文件,发送网络请求),那后面的任务都必须排队等着,会拖延整个程序的执行.
为解决这个问题,js语言将任务的执行模式分成两种: 同步 和 异步
同步模式: 后一个任务等前一个任务结束,然后再执行,程序执行的顺序与任务的排序顺序是一致的,同步的
异步模式: 每一个任务有一个或多个回调函数callback(),前一个任务结束,不是执行后一个任务,而是执行回调函数,所以程序的执行顺序与任务的排序顺序是不一致的,异步的
解决方案: 回调函数, 事件监听(Event) , 发布订阅模式, Promise
回调函数
将一个函数作为参数传递给另一个函数,作为参数的这个函数就是回调函数
// 同步回调
var callback = function(arg){
console.log('callback totle',arg)
}
function fn(arg1,arg2,callbackFn){
var totle = arg1 + arg2
callbackFn(totle)
console.log('myfunction totle',totle)
}
fn(11,22,callback)
// callback totle 33
// myfunction totle 33
// 异步回调
function fn1(fn2){
setTimeout(function(){
console.log('这里是1')
fn2()
},1000)
}
function fn2(){
console.log('这里是2')
}
fn1(fn2)
// 打印 这里是2 这里是1
事件监听
任务的执行不取决于代码的顺序,而取决某个事件是否发生
//JQuery写法
fn1.on('done',fn2);
// 当fn1发生done事件,就执行fn2
function fn1(){
setTimeout(function(){
// fn1的任务代码
fn1.trigger('done')
},1000)
}
// fn1.trigger('done')表示,执行完成后,立即触发done事件,从而开始执行fn2
发布/订阅 与事件监听本质是一样的
Promise
a.异步编程的一种解决方案
b.主要用于异步计算(操作),避免界面冻结(任务)
c. 可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
d. 可以在对对象之间传递和操作Promise,帮助我们处理队列
new Promise((resolve,reject)=>{
// 耗时的异步操作
setTimeout(()=>{
console.log('假设是耗时的网络请求')
resolve('成功') // 数据处理完成
// reject('失败') // 数据处理报错
},1000)
}).then(
(res)=>{console.log(res)}, // 成功
(err)=>{console.log(err)} // 失败
)
reslove作用是, 将Promise对象的状态从 ‘未完成’ 变为 ‘成功’ (即从pending 变为 resolved), 在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
reject作用是, 将Promise对象的状态从 ‘未完成’ 变为 ‘失败’ (即从pending变为reject), 在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去
Promise的三个状态
- pending [待定] 初始状态
- fulfilled [实现 ] 操作成功
- reject [ 被否决] 操作失败
当Promise状态发生改变, 就会触发then( ) 里的响应函数处理后续步骤,promise状态只有两种可能,从pending 变为 fulfilled, 或者从pending 变为 reject, 状态一经改变就不会变了
new Promise((resolve) => {
setTimeout(() => {
resolve('qwert')
}, 1000);
}).then((res) => {
console.log(res);
return new Promise((resolve) => {
setTimeout(() => {
resolve('yuiop')
}, 1000);
})
}).then(res => {
console.log(res);
})
.then()
- 接收两个函数作为参数,分别代表fulfilled (成功) 和 rejected (失败)
- .then()返回一个新的Promise实例,所以可以链式调用
- 当前面的Promise状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行
- 状态响应函数可以返回新的promise,或者其他值,不返回值可以认为返回看一个null
- 如果返回新的promise,那么下一级.then()会在新的promise状态改变之后执行
- 如果返回其他任何值,则会立即执行下一级.then()
axios
是由promise封装的一个http的库,axios本身就是一个promise,会继承某些方法,比如 .then()
async/await
是es6的promise的升级版,更好地处理then链式调用,async必须声明的是一个function, await只能放在这个函数内部使用.