先来说一下Promise的三种状态
pending - 进行中
fulfilled - 成功
rejected - 失败
Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
但Promise对象的状态不受外界影响,Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
状态的改变(或者说决议)不可逆,一旦决议就不能再更改。
任何时候都可以得到这个结果,Promise对象的状态改变,只有两种可能:从pending变为fulfilled 或者 从pending变为rejected,只要这两种情况中的一种发生,其状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。
这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
进阶开始,让我们手写一个promise
概念: promise接受一个函数 有三种 状态 俩个回调
写一个构造函数接收一个参数 有三种状态 成功结果 失败结果 成功回调 失败 回调
构造函数的原型有一个.then 方法 接收俩个参数 判断状态 如果成功调用 成功函数 失败 调用失败函数 pending 就存起来。
代码如下:
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// promise接受一个函数 有三种 状态 俩个回调
// 写一个构造函数接收一个参数 有三种状态,此外还有:成功结果 失败结果 成功回调 失败回调
// 构造函数的原型有一个.then 方法 接收俩个参数 判断状态 如果成功调用 成功函数 ;失败 调用失败函数 pending 就存起来
function Promise (executor) {
var _this = this
this.state = PENDING // 状态
this.value = undefined // 成功结果
this.reason = undefined; // 失败原因
this.onFulfilled = [];//成功的回调
this.onRejected = []; //失败的回调
function resolve (value) {
if (_this.state === PENDING) {
_this.state = FULFILLED
_this.value = value
_this.onFulfilled.forEach(fn => fn(value))
}
}
function reject (reason) {
if (_this.state === PENDING) {
_this.state = REJECTED
_this.reason = reason
_this.onRejected.forEach(fn => fn(reason))
}
}
try {
executor(resolve, reject)
} catch (e) {}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
if (this.state === FULFILLED) {
typeof onFulfilled === 'function' && onFulfilled(_this.value)
}
if (this.state === REJECTED) {
typeof onRejected === 'function' && onRejected(_this.reason)
}
if(this.state === PENDING){
typeof onFulfilled === 'function' && this.onFulfilled.push(onFulfilled)
typeof onRejected === 'function' && this.onRejected.push(onRejected)
}
}
// module.exports = Promise;
var p = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(4)
}, 0)
})
p.then((res)=>{
//4 res
console.log(res, 'res')
})
p.then((res1)=>{
//4 res1
console.log(res1, 'res1')
})
一、对于resolve,reject简单理解
我们先构建一个Promise
//构建Promise
var promise = new Promise(function (resolve, reject) {
if (/* 异步操作成功 */) {
resolve(data);
} else {
/* 异步操作失败 */
reject(error);
}
});
这种方式类似构建对象,使用new来构建一个Promise。
Promise接受一个「函数」作为参数,该函数的两个参数分别是resolve和reject。这两个函数就是就是「回调函数」,由JavaScript引擎提供。
Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数。
//promise.then(onFulfilled, onRejected);
promise.then(function(data) {
// do something when success
}, function(error) {
// do something when failure
});
then方法会返回一个Promise。它有两个参数,分别为Promise从pending 变为 fulfilled和rejected时的回调函数(第二个参数非必选)。这两个函数都接受Promise对象传出的值作为参数。
.catch()
该方法是.then(undefined, onRejected)的别名,用于指定发生错误时的回调函数。
promise.then(function(data) {
console.log('success');
}).catch(function(error) {
console.log('error', error);
});
/*******等同于*******/
promise.then(function(data) {
console.log('success');
}).then(undefined, function(error) {
console.log('error', error);
});
promise对象的错误,会一直向后传递,直到被捕获。即错误总会被下一个catch所捕获。then方法指定的回调函数,若抛出错误,也会被下一个catch捕获。catch中也能抛错,则需要后面的catch来捕获。
sendRequest('test.html').then(function(data1) {
//do something
}).then(function (data2) {
//do something
}).catch(function (error) {
//处理前面三个Promise产生的错误
});
此处要注意,promise一旦resolve(即成功状态)了再抛错,也不会变为rejected(失败状态),也就不会被catch了,代码如下:
var promise = new Promise(function(resolve, reject) {
resolve();
throw 'error';
});
promise.catch(function(e) {
console.log(e); //This is never called-永远不会被触发
});
如果没有使用catch方法指定处理错误的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应
关于promise中reject和catch的问题
一、reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch
var p1=new Promise((resolve,rej) => {
console.log('没有resolve')
//throw new Error('手动返回错误')
rej('失败了')
})
p1.then(data =>{
console.log('data::',data);
},err=> {
console.log('err::',err)
}).catch(
res => {
console.log('catch data::', res)
})
结果为:
没有resolve
err:: 失败了
then中没有第二个回调的情况
var p1=new Promise((resolve,rej) => {
console.log('没有resolve')
//throw new Error('手动返回错误')
rej('失败了')
})
p1.then(data =>{
console.log('data::',data);
}).catch(
res => {
console.log('catch data::', res)
})
结果为:
没有resolve
catch data:: 失败了
二、resolve的东西,一定会进入then的第一个回调,肯定不会进入catch
var p1=new Promise((resolve,rej) => {
console.log('resolve')
//throw new Error('手动返回错误')
resolve('成功了')
})
p1.then(data =>{
console.log('data::',data);
}).catch(
res => {
console.log('catch data::', res)
})
结果为:
resolve
data:: 成功了
不会进入catch的情况,只要resolve(即成功)了,就算抛出err,也不会进入catch
var p1=new Promise((resolve,rej) => {
console.log('resolve')
//throw new Error('手动返回错误')
resolve('成功了')
})
p1.catch(
res => {
console.log('catch data::', res)
})
结果:
resolve //即成功以后永远不会进入catch
throw new Error 的情况和rej一样,但是他俩只会有一个发生
另外,网络异常(比如断网),会直接进入catch而不会进入then的第二个回调