es6之Promise

Promise

Promise介绍

1. Promise是异步编程的一种解决方案,比传统的解决方案—回调函数和事件—更合理;

2. Promise其实就是一个容器,里面保存了当异步事件调用后可能发生的结果;

Promise的三种状态

3. Promise对象是一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有当异步操作结束后,才能确定当前的状态,其他操作无法改变其状态;并且状态一旦发生改变,便不会再发生改变,装填的改变只有两种可能:从pending改变为fulfilled—异步操作成功;从pending改变为rejected—异步操作失败。一旦状态发生了改变,后面再对Promise对象添加回调函数,也会立即得到该结果

  1. pending:等待状态,比如正在进行网络请求,或者定时器还没到时间
  2. fulfill:成功状态,当主动回调resolve时,就从pending改变为fulfill状态,并回调.then()
  3. reject:拒绝状态,当主动回调reject后,从pending改变为reject状态,并回调.catch()

4. Promise的回调函数中有两个参数resolve和reject,这是由JavaScript自身提供,当异步操作获得的结果,无论早晚都没关系,它的回调将是以下回调之一:

  1. resolve(value)—如果任务成功完成该并带有结果value
  2. reject(error)—如果出现了error,返回error,error即为error对象
let promise = new Promise((resolve, reject)=>{
    resolve('success'); 
    reject(new Error('failed')); //将被会忽略
    setTimeout(()=>reslove('done'));//也会被忽略
})

promise的基本使用:

resolve和reject是两个函数,通常情况下,根据请求数据的成功与否来决定调用哪一个函数。

  1. 如果成功,那就调用resolve(data),然后.then会被回调
  2. 如果失败,那就调用reject(error),然后.catch会被回调
const promise = new Promise((reslove, reject)=>{
    setTimeout(()=>{
        reslove('success');
        reject('failed');
    },1000)
}).then(data=>{
    console.log(data);
}).catch(error=>{
    console.log(error);
})

Promise链式调用

image-20200521151217443.png

无论是then还是catch,最后都可以返回一个Promise对象,因此可以对Promise来链式调用,同时可以用Promise来包装一下数据再返回:

  1. Promise.resolve():将数据包装成Promise对象,并在内部回调resolve()函数,直接返回数据将默认是这种形式
  2. Promise.reject():将数据包装成Promise对象,并在内部回调reject函数
    const promise = new Promise((resolve, reject)=>{
        setTimeout(()=>{
            resolve('success');
        },1000)
    }).then(message=>{
        console.log(message);  //success
        return Promise.resolve(message + '111');
    }).then(message=>{
        console.log(message);  //success111
        return message + '222';  //若返回的是resolve,则可以直接返回数据
    }).then(message=>{
        console.log(message); //success111222
        return Promise.reject(message + 'error');  //由于这里是reject,因此不会执行下面的.then了,而是执行catch
    }).then(message=>{
        console.log(message);  //没有输出,不会执行
        return message + '333';
    }).catch(message=>{
        console.log(message);  //success111222error
    }).finally(()=>{  //finally是不管promise的状态如何,都会执行的操作
        console.log('promise is finished');
    })

Promise方法

Promise.prototype.*为Promise实例的方法

Promise.*为Promise对象的方法

Promise.prototype.then()

.then方法是为Promise实例添加状态改变时的回调函数,其参数都是函数:第一个参数是resolve状态的回调函数,第二个参数(可选)是reject状态的回调函数。不过尽量少使用第二个参数,而是使用catch方法

then方法返回的是一个新的Promise实例,因此可以进行链式调用(如上面的代码)

const promise = new Promise((resolve,reject)=>{
    resolve('success');  //状态一旦确定就不会再改变
    reject('error'); //因此该状态不会发生
}).then((message)=>{
    console.log(message); //success
    return message + '1111'; //返回的将是一个新的promise实例,简写形式默认是Promise.resolve()
},(error)=>{
    console.log(error); //不会执行
}).then(
    message => console.log(message); //上一个then函数中的返回值作为参数传入下一个then函数的回调函数中
)

Promise.prototype.catch()

.catch()方法是.then(null, reject)或.then(undefined,reject)的别名,相当于是then方法的第二个参数的回调函数,用于当异步操作发生错误时的回调函数

const promise = new Promise((resolve,reject)=>{
    reject('error了'); 
}).catch(
	error => console.log(error);  //error了
)

//等同于
const promise = new Promise((resolve,reject)=>{
    reject('error了'); 
}).then(
	null,
    error => console.log(error) //error了
)

若不使用catch,Promise对象抛出的错误不会传递到外层代码,也就是说不会影响到外部代码的运行。因此一般情况下,Promise对象要跟上一个catch方法来捕获错误,如果有错就捕获,如果没错就继续执行后面的代码

const promise = new Promise((resolve,reject)=>{
    resolve(x*2);  //会报错,因为x未定义
}).then(
	()=>console.log('programmer is finished')
)
setTimeout(()=>{console.log('aaaaa')},3000)
//Uncaught (in promise) ReferenceError: x is not defined
//aaaaa  虽然报错,但是也会继续执行后面的代码

Promise.prototype.finally()

.finally()方法用于表示Promise对象最后的状态,不管异步操作成功与否,都会执行该方法。

并且finally方法的回调函数不接受任何参数,该方法与状态无关,不管Promise是啥状态,最后都会执行

const promise = new Promise((resolve, reject)=>{
    resolve('success');
}).then(
	message => console.log(message)
).catch(
	error => console.log(error)    
).finally(
    ()=> console.log('finished')
)

finally方法其实是then方法的特例

const promise = new Promise((resolve, reject)=>{
    resolve('success');
})
promise.finally(
	()=>{console.log('finished');}
)

//等同于
promise.then(
	() => console.log('finished'),
    () => console.log('finished')
)

Promise.all()

.all()方法是将多个Promise实例,组合成一个新的Promise实例

const p1 = new Promise((res,rej)=>{});
const p2 = new Promise((res,rej)=>{});
const p3 = new Promise((res,rej)=>{});
const promise = Promise.all([p1, p2, p3]);

Promise.all()方法接受一个数组作为参数,p1,p2,p3都是Promise实例。若不是,则会调用Promise.resolve方法,将参数转换为Promise实例,再进一步处理。当然,all()方法的参数不一定是数组,只要具备Iterator接口即可。

而promise的状态由p1,p2,p3共同决定的,

若p1,p2,p3的状态都是fulfilled,promise的状态才会是fulfilled,并且此时的p1,p2,p3的返回值组成一个数组,传递给promise的回调函数

若p1,p2,p3中有一个的状态是reject,那promise的状态就变成了rejected,并且此时被reject的实例的返回值,传递给promise的回调函数

const p1 = new Promise((resolve,reject)=>{
    resolve('resolve1');
})
.then(res => res)
.catch(err => err);
const p2 = new Promise((resolve,reject)=>{
    throw new Error('报错了');
})
.then(res => res)
.catch(err => err);

Promise.all([p1,p2])
.then(res=>console.log(res))
.catch(err => console.log(err))
//["resolve1", Error: 报错了]
/*p1是resolved状态,p2首先是rejected状态,但是p2有自己的catch
方法,会返回一个新的Promise实例,并且默认是resolved方法,所以最
后返回的是resolved,因此all方法的参数的两个promise实例都是
resolved,因此会调用then方法*/

const p1 = new Promise((resolve,reject)=>{
    resolve('resolve1');
})
.then(res => res)
.catch(err => err);
const p2 = new Promise((resolve,reject)=>{
    throw new Error('报错了');
})
.then(res => res)
.catch(err =>{
    return Promise.reject(err); //手动返回reject,所以p2最终状态为resolved
});

Promise.all([p1,p2])
.then(res=>console.log(res))
.catch(err => console.log(err))
//Error: 报错了
//有一个是reject,因此就返回对应reject的返回值

Promise.prototype.race()

.race()方法.all()方法类似,将多个Promise实例包装成一个Promise实例

const p = Promise.race([p1,p2,p3]);

p1,p2,p3中只要有一个实例状态先改变,p的状态也就跟着改变,先改变状态的p的返回值,就传递给p的回调函数

Promise.resolve()、Promise.reject()

Promise.resolve()和Promise.reject()都是将现有对象转换为Promise对象

Promise.resolve('bar');
//相当于
new Promise(resolve=>resolve('bar'))
Promise.reject('bar');
//相当于
new Promise(reject=>reject('bar'))

try…catch

try…catch是一种错误处理,当程序遇到错误时,就会在控制台输出错误,并停止运行,这可能不太合理。因此使用一种语法结构try…catch,程序即使发生了错误,也能进行 更合理的操作,而不会立即停止

//如果try中的代码没有错误,则catch中的代码不会执行;若出现错误,try中的代码立即停止执行,跳转到catch中的代码
try{
    //执行的代码
}catch(err){
    //错误捕获
}

try…catch是同步工作的

如果在try中的代码发生了异常,假如在setTimeout函数中,try…catch不会捕获到异常

try{
    setTimeout(()=>{
        console.log(a); //程序到这就停止了,因为是同步执行的,而不会去执行catch了
    },2000)
}catch(e){
    console.log('error了')
}
//将try...catch函数放到setTimeout函数中,这样就能捕获错误了
setTimeout(()=>{
    try{
        console.log(a);
    }catch(err){
        console.log('error了')}
},2000)

try…catch…finally

try…catch还有一个代码子句,就是finally,它在所有情况下都会执行

try {
    //尝试执行的代码
  console.log('try');
} catch (e) {
    //处理error
  console.log( 'catch' );
} finally {
    //总是会执行的代码
  console.log( 'finally' );
}

Error对象

如catch中的error参数,这个error可以用任何变量代替,这是一个Error对象

对于所有的Error对象,都有如下属性

  1. name:对于一个未定义变量的错误,name是’ReferenceError’
  2. message:对error的详细描述
  3. stack: 当前的调用栈:用于调试目的的一个字符串,其中包含有关导致 error 的嵌套调用序列的信息
let error = new Error('this is an error');
console.log(error.name); //Error
console.log(eror.message); //this is an error

throw操作符

throw操作符可以生成一个自定义的error对象

const promise = new Promise((resolve, reject)=>{
    throw new Error('failed');  //相当于reject
}).catch((error)=>{
    console.log(error); //Error: failed
});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值