异步编程与Promise的关系
异步代码无法通过return来返回值(有时间差),解决这个问题需要使用回调函数基于“回调函数”的异步带来的问题,使用回调函数时会导致“回调地狱”(代码可读性低且不好调试)的情况Promise可以帮助我们解决异步回调函数的这个问题,因为Promise就是一个用来存储数据的容器它拥有着一套创建Promise特殊的存取数据的方式这个方式使得它里边可以存储异步调用的结果
Promise的作用与用法
Promise的作用
Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码;让代码更加的直观。有了Promise对象,就可以将异步操作以同步的操作的流程表达出来,避免了层层嵌套的回调函数。
总结:可以将原先不可控的回调通过promise转为更加可控更清晰的方式表达,更加高效,更便于维护。
示例:未使用promise,回调必须层层嵌套
$.ajax(url1, function(data1){
// do something1...
$.ajax(url2, function(data2){
// do something2...
$.ajax(url3, function(data3){
// do something3...
})
});
});
如果有多个嵌套,导致代码不够直观,逻辑梳理上会更加的困难。并且这几个操作都是有执行的一个依赖关系,需要等待上一个请求完成才可以进行下一个请求,而这些本身就是异步,这样的等待是没有必要的。所以promise可以帮助我们解决这一部分痛点。
Promise的用法
1、首先我们new一个Promise,将Promise实例化
2、然后在实例化的promise可以传两个参数,一个是成功之后的resolve,一个是失败之后的reject
3、Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数
var promise = function(isReady){
return new Promise(function(resolve, reject){
// do somthing, maybe async
if (isReady){
return resolve('成功执行');
} else {
return reject('出错了');
}
});
}
//Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。
promise(true).then(function(value){
// success,这里是resolve的回调函数
console.log(value); //hello world
}, function(err){
// failure,这里是reject的回调函数
console.log(err)
})
上述代码是执行成功,返回成功执行,
失败后的返回值,可以把promise(true).then...这里改为 promise(false).then...可以在控制台调试
Promise在实际环境下的应用
应用场景:验证多个请求结果是否都是满足条件
function verify1(content){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(true)
},200)
})
}
function verify2(content){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(true)
},700)
})
}
function verify3(content){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(true)
},300)
})
}
Promise.all([verify1('校验字段1的内容'),verify2('校验字段2的内容'),verify3('校验字段3的内容')]).then(result=>{
console.log(result)//[true, true, true]
let verifyResult = result.every(item=>item)
//验证结果
console.log(verifyResult?'通过验证':'未通过验证')// 通过验证
}).catch(err=>{
console.log(err)
})
async/await的作用与用法
通过async可以快速创建异步函数,异步函数的返回值会自动封装到一个Promise中返回
,在async声明的异步函数中可以使用await关键字来调用异步函数
await用来解决链式调用太多的问题
function sum(a,b) {
return new Promise(resolve => {
setTimeout(() => {
resolve(a+b)
}, 2000);
})
}
/*
async function fn3() {
sum(123,456)
.then(r => sum(r,8)
.then(r => sum(r,9)
.then(r => console.log(r)
}
*/
let result = await sum(123,456)
// await表示等待,当我们通过await去调用异步函数时,它会暂停代码的运行;直到异步代码执行有结果时,才会将结果返回
// 注意:await只能用于 async声明的异步函数中,或es模块的顶级作用域中
// await阻塞的是异步函数内部的代码,不会影响外部代码
// 通过await调用异步代码时,需要通过try-catch处理异常
// 如果async声明的异步函数中没有写await,那么它里边的代码就会依次执行
async function fn4() {
console.log(1)
/*
当我们使用await调用函数后,当前函数后边的所有代码
会在当前函数执行完毕后,被放入到微任务队伍里(范围在async里)
*/
await console.log(2)
console.log(3)
}
fn4()
console.log(4)
//结果:1 2 4 3