前端高频面试题 promise
ps:绝大部分资料来源于网络,只是添加了一些更容易理解的话,方便我这种小白快速记忆面试。。。
promise概述
Promise是跟随es6出来对异步回调地狱的一种很好的解决方案。
那么什么是回调地狱?
如果没有promise,我们想发送一个异步请求需要
// 请求 代表 一个异步网络调用。
// 请求结果 代表网络请求的响应。
请求1(function(请求结果1){
处理请求结果1
})
看起来还行是吧,但是现在来了,我们需要用上一个请求结果来发送下一个请求。然后再再再再发送请求,于是,回调地狱来了。
请求1(function(请求结果1){
请求2(function(请求结果2){
请求3(function(请求结果3){
请求4(function(请求结果4){
请求5(function(请求结果5){
请求6(function(请求结果3){
... //此处省略五百个请求,你慌不慌?
})
})
})
})
})
})
于是,一大堆问题来了,例如:
·代码臃肿。
·可读性差。
·耦合度过高,可维护性差。
·代码复用性差。
·容易滋生 bug,且不容易发现
·只能在回调里处理异常。
那咋整啊?于是promise来了
promise三种状态
//Promise是异步的一种解决方案,他有三种状态:
pending //等待/进行中
fulfilled //完成
rejected //失败/错误
promise用法
首先初始化一个 Promise 对象,可以通过两种方式创建, 这两种方式都会返回一个 Promise 对象。
方法1、new Promise(fn)
方法2、Promise.resolve(fn)
然后调用上一步返回的 promise 对象的 then 方法,注册回调函数。
then 中的回调函数可以有一个参数,也可以不带参数。如果 then 中的回调函数依赖上一步的返回结果,那么要带上参数。比如
new Promise(fn)
.then(fn1(value){
//处理value
})
学废了? 来个小题目试试?
以下程序代码运行后结果是什么?
new Promise(function(resolve, reject) {
console.log(1);
resolve('success');
console.log(2);
reject('error');
console.log(3);
}).then(function(value) {
console.log('then', value);
}).catch(function(err) {
console.err('error:', err);
});
。
。
。
。
。
。
。
。
。
。
提示:promise是异步的
。
。
。
。
。
答案:
1
2
3
then success
再来一个
const promise = new Promise((resolve, reject) => {
console.log(1)
resolve()
console.log(2)
})
promise.then(() => {
console.log(3)
})
console.log(4)
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
答案
1
2
4
3
promise状态变化
Promise必须存在一种状态(pending或fulfilled或rejected)。如果为pending状态,那么可以转换到其他的两个状态;如果为fulfilled状态,那么必须有一个值,并且值和状态不可改变;如果为rejected状态,那么必须有一个原因,并且状态和原因不可改变。
目前只研究透了这么一丢丢,后续玩明白了继续更新。
还有,那什么是resolve和reject呢?以及使用方法
首先实例化Promise时需要传入一个函数excutor作为参数,并且在Promise构造函数执行时同步执行。
var p = new Promise(function(resolve,reject){
var timer = setTimeout(function(){
console.log('执行操作1');
},1000);
});
我们可以看到1s后在控制台输出相应的结果,这就说明在实例化过程中,作为参数的excutor函数也会执行。
从上面的实例中我们看到,excutor函数还有两个参数resolve和reject,其实这两个参数也是函数,在excutor执行时被调用,下面我们具体来谈谈resolve和reject的用法。
———————————————————————————
当我们在excutor函数中调用resolve方法时,Promise的状态就变成fulfilled,即操作成功状态,还记得上面Promise.prototype上面的then和catch方法吗?当Promise状态为fullfilled状态时执行then方法里的操作,注意了,then方法里面有两个参数onfulfilled(Promise为fulfilled状态时执行) 和onrejected(Promise为rejected状态时执行),步骤如下:
1,实例化Promise(new Promise(function(resolve,reject)))
2,用Promise的实例调用then方法
具体来看下面的例子:
resolve方法
var p = new Promise(function (resolve, reject) {
var timer = setTimeout(function () {
console.log('执行操作1');
resolve('这是数据1');
}, 1000);
});
p.then(function (data) {
console.log(data);
console.log('这是成功操作');
});
简单的理解就是调用resolve方法,Promise变为操作成功状态(fulfilled),执行then方法里面onfulfilled里的操作。其实then里面的函数就是我们平时所说的回调函数,只不过在这里只是把它分离出来而已。我们可以看到控制台上的输出结果如下所示:
执行操作1
这是数据1
这是成功操作
reject方法
看了上面的实例,我相信应该也很容易理解reject方法了,就是调用reject方法后,Promise状态变为rejected,即操作失败状态,此时执行then方法里面onrejected操作,上面我们提到了then方法有两个参数,一种是Promise状态为fulfilled时执行(onfullfilled),一种是Promise状态为rejected时执行(onrejected),其实就是类似于jquery里的hover方法里面的两个参数一样,来看看下面的例子:
var p = new Promise(function (resolve, reject) {
var flag = false;
if(flag){
resolve('这是数据2');
}else{
reject('这是数据2');
}
});
p.then(function(data){//状态为fulfilled时执行
console.log(data);
console.log('这是成功操作');
},function(reason){ //状态为rejected时执行
console.log(reason);
console.log('这是失败的操作');
});
我们可以看到这样的结果
这是数据2
这是失败的操作
cash方法
我们注意到除了then方法外,Promise原型上还有另外一个叫catch的方法,那么这个方法的作用是什么呢?其实跟then方法中的第二个参数一样,就是在Promise状态为rejected时执行,then方法捕捉到Promise的状态为rejected,就执行catch方法里面的操作,下面用catch方法改写上面reject用法里面的例子,如下所示:
var p = new Promise(function (resolve, reject) {
var flag = false;
if(flag){
resolve('这是数据2');
}else{
reject('这是数据2');
}
});
p.then(function(data){
console.log(data);
console.log('这是成功操作');
}).catch(function(reason){
console.log(reason);
console.log('这是失败的操作');
});
执行结果和上面reject用法的例子一样。
这是数据2
这是失败的操作