1,什么是promise?
1,抽象表达:promise是js中进行一步编程的新的解决方案(旧的是—纯回调函数)
2,具体表达:
语法上讲
:promise是一个构造函数,可以new创建一个 promise
功能上讲
:promise对象用来封装一个异步操作并可以获取其结果
3,目的:解决回调地狱问题
注:promise 状态改变中,resolved为成功回调, reject失败回调;只有两种状态,且一个promise对象只能变一次;无论变为成功还是失败,都会有一个结果数据;成功的结果数据一个称为 value ,失败的结果数据一般称为 reason
4,promise 的基本使用
var promise=new Promise(function(){})
注:这是一个异步操作,其中function 内部写的就是具体的异步操作
2,why—为什么用?
1,作用:指定回调函数的方式更加灵活
旧的:必须在启动异步任务前指定
promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数
注:promise的实例是一个异步操作,无法使用return把操作的结果返回给调用者,这时候,只能使用回调函数的形式,来把成功 或 失败的结果,返回给调用者;
2,promise 原型上的 .then 方法是预定为后面成功和失败的回调,成功的回调必须传,失败的回调可以不传
3,支持链式调用,可以解决回调地狱问题
4,async / await:回调地狱的终极解决方案
getFIiePath(path){
var promise= new Promise(function(resolve,reject){
if (err) return reject ( err ){ }
resolve(data){ }
})
return promise;
},
getFIiePath(xxx_路径).then( succse( data){ } , fail(err ){ } )
3,怎么用?
callback:这个只是表示他是一个回调函数的占位符,他只是作为一个参数,具体的形式,是看传的函数是什么 callback 只有两种形式:成功回调(第一个位置),失败回调(第二个位置)
1,上一个 .then 中,return 一个新的 promise 实例,可以继续用下一个 .then 来处理
2,promise 一旦出错,进行捕获,继续执行下去,否则,不会继续执行
3,如果不想前面的 promise 出错,操作被终止,可以为每个 promise 指定失败的回调捕捉
getFile("./files/1.txt")
.then(function(data){
console.log(data)
return getFile("./files/2.txt")
})
.then(function(data){
console.log(data)
return getFile("./files/3.txt")
})
.then(function(data){
console.log(data)
})
.catch(function(err){
// catch 捕获 promise 中抛出的所有异常
console.log(err)
})
注:出错类型在下面有补充说明,
4,promise 的工作流程
4,async和await — 异步函数
同步函数:立即执行,完全执行完了才结束,不会放入回调队列中
异步函数:不会立即执行,会放入回调队列中将来执行
1,普通函数 中使用 async关键字,就会变为异步函数,
2,异步函数中,return
后面默认被包裹了一层Promise
对象,return
关键字代替了reslove
方法
3,异步函数中,使用throw
关键字抛出程序异常,
4,调用异步函数再链式调用 .then方法,获取异步函数中执行结果
5,调用异步函数再链式调用 .catch方法,获取异步函数中错误信息
async function fn(){
throw '发生了写错误'; // 当 throw 方法执行之后,后面的方法就不会继续执行
return 123
}
fn().then(function(data){
console.log(data); // 123
}).catch((err)=>{
console.log(err)
})
await 关键字
1,
await
只能出现在async异步函数中
2,await Promise await
后面只能写Promise
对象,写其他的API
不可以,
3,await
关键字可以暂停异步函数向下执行,等待Promise
返回结果后,再向下继续执行函数
3,await
使用异步代码,但是执行时是按照同步形式代码执行顺序
async function p1(){
return 'p2'
}
async function p2(){
return 'p3'
}
async function p3(){
return 'p3'
}
function fn(){
let res1 = await p1()
let res2 = await p2()
let res3 = await p3()
}
注:上段代码执行的顺序是,先执行 p1() ,得到结构之后赋值给res1,再执行执行 p2() ,得到结构之后赋值给res2,执行 p3() ,得到结构之后赋值给res3,虽然是异步函数,但是按照顺序依次执行
2,Promise.all ( );得到多个promise的结果
function test(x){
return new Promise((resolve, reject)=>{
if(x >3){
resolve()
}else{
reject()
}
})
}
Promise.all(test(5),test(2)).then((res)=>{
console.log('成功的回调1')
}).then(()=>{
console.log('成功的回调2')
}).catch(()=>{
console.log('失败的回调')
})
3,Promise.race( ):返回最先完成的一个任务结果,其他任务依然执行,但是打印不出来
function test(x){
return new Promise((resolve, reject)=>{
if(x >3){
resolve()
}else{
reject()
}
})
}
Promise.race(test(5),test(2)).then((res)=>{
console.log('成功的回调1') // 只要 test(5),test(2) 任意一个返回成功,都可以打印出结果
}).then(()=>{
console.log('成功的回调2')
}).catch(()=>{
console.log('失败的回调')
})
4,用 await 获得多个promise结果
async function test(){
try{
let n = await Promise.all([text(5),text(2)])
console.log(n)
}catch(error){
console.log(error)
}
}
test()
如果你没有在async函数中写return,那么Promise对象resolve的值就是undefined,如果你写了return,那么return的值就会作为你成功的时候传入的值
promise 的缺点
- promise一旦新建就会立即执行,无法中途取消
- 当处于pending状态时,无法得知当前处于哪一个状态,是刚刚开始还是刚刚结束
- 如果不设置回调函数,promise内部的错误就无法反映到外部
- promise封装ajax时,由于promise是异步任务,发送请求的步骤会被延后到整个脚本同步代码执行完,并且将响应回调函数延迟到现有队列的最后,如果大量使用会大大降低了请求效率。
补充:
1,常见的内置错误
error:所有错误的父类型
referenceError:引用的变量不存在—引用不存在的变量会报错,如果没有捕获错误,那么下面的代码就不会继续执行
typeError:数据类型不正确的错误—设置一个变量,但是他不存在某些属性,当运行时候,会报此错
rangeError:数据值不在其所允许的范围内
syntaxError:语法错误—不符合常规语法的错误会报错
2,错误处理
1,捕获错误:try ... catch
如果程序出错,还行让程序继续执行,那么使用捕获错误
try {
let b;
console.log(b.xxx)
} catch (error) {
console.log(error)
}
console.log('出错之后,还执行的错误,因为上面捕获了')
注:每个error都有两个属性,message与stack
2,抛出错误:throw error
try {
something()
} catch (error) {
console.log(error.message)
}
function something() {
if (Date.now() % 2 === 1) {
console.log('当前时间为奇数,可以执行')
} else {
throw new error('当前时间为偶数,不可以执行')
}
}
3,错误对象
message属性:错误相关信息
stack属性:函数调用栈记录信息