一、什么是promise
Promise的出现,原本是为了解决回调地狱的问题。以我们平常使用的ajax请求为例:
传统js方法:
getData(method, url, successFun, failFun){
var xmlHttp = new XMLHttpRequest();
xmlHttp.open(method, url);
xmlHttp.send();
xmlHttp.onload = function () {
if (this.status == 200 ) {
successFun(this.response);
} else {
failFun(this.statusText);
}
};
xmlHttp.onerror = function () {
failFun(this.statusText);
};
}
使用Promise:
getData(method, url){
var promise = new Promise(function(resolve, reject){
var xmlHttp = new XMLHttpRequest();
xmlHttp.open(method, url);
xmlHttp.send();
xmlHttp.onload = function () {
if (this.status == 200 ) {
resolve(this.response);
} else {
reject(this.statusText);
}
};
xmlHttp.onerror = function () {
reject(this.statusText);
};
})
return promise;
}
getData('get','www.xxx.com').then(successFun, failFun)
很显然,我们把异步中使用回调函数的场景改为了.then()
、.catch()
等函数链式调用的方式。基于promise
我们可以把复杂的异步回调处理方式进行模块化。
大致Promise的结构可以分成如下:
Promise构造函数接受一个函数作为参数,函数里面有两个参数resolve和reject分别作为执行成功或者执行失败的函数
var promise=new Promsie(function(resolve,rejec){
if(/*异步执行成功*/){
resolve(value);
}else{
reject(error);
}
})
通过then设置操作成功之后的操作,接受两个函数作为参数,第一个成功的操作必写,第二个失败后的操作可选
promise.then(function(){
//回调执行成功之后的操作
},function(){
//回调执行失败之后的操作,可选
});
熟悉了Promise的结构后我们要了解一下Promise构造函数的一些属性和方法,可以看出,
Promise有三种状态:
1、pending(异步操作未完成的状态)
2、resolved(异步操作成功的状态)
3、rejected(异步操作失败的状态)
两种方法:
1.resolve()
2.reject()
resolve
函数的作用是,将Promise
对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject
函数的作用是,将Promise
对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
当然Promise实例生成后还能再调用一种方法:
then()
then
方法可以接受两个回调函数作为参数。第一个回调函数是Promise
对象的状态变为resolved
时调用,第二个回调函数是Promise
对象的状态变为rejected
时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise
对象传出的值作为参数。
了解好这些后我们就可以自己来写一个简单的Promise构造函数了
二、js实现Promise
我将自己写的构造函数命名为NewPromise
class NewPromise {
constructor(executor) {
if (typeof executor !== 'function') {
throw new Error('Executor must be a function');
}
this.state = 'pending';
const resolve = res => {
if (this.state !== 'pending') {
return;
}
this.state = 'resolved';
this.internalValue = res;
};
const reject = err => {
if (this.state !== 'pending') {
return;
}
this.state = 'rejected';
this.internalValue = err;
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onResolved, onRejected) {
if (this.state === 'resolved') {
onResolved(this.internalValue);
} else if (this.$state === 'rejected') {
onRejected(this.internalValue);
}
}
}
let p = new NewPromise(resolve => {
resolve('Hello');
});
p.then(res => console.log(res)); //Hello
看起来好像没啥问题,但是仔细观察便能知道我们并没有处理如果在调用的时候状态还是pending的情况,比如我们使用setTimeout函数:
let p = new NewPromise(resolve => {
// resolve('Hello');
setTimeout(() => resolve('Hello'), 100);
});
p.then(res => console.log(res));
这个时候可以看到控制台没有任何输出。这要怎么解决呢,我们可以使用一个变量来存储,当Promise状态还是pending的时候,我们就将onResolved和onRejected存储到这个变量中,当执行完Promise之后再来调用它。代码如下:
class NewPromise {
constructor(executor) {
if (typeof executor !== 'function') {
throw new Error('Executor must be a function');
}
this.state = 'pending';
this.statesSave = [];
const resolve = res => {
if (this.state !== 'pending') {
return;
}
this.state = 'resolved';
this.internalValue = res;
for (const { onResolved } of this.statesSave) {
onResolved(res);
}
};
const reject = err => {
if (this.state !== 'pending') {
return;
}
this.state = 'rejected';
this.internalValue = err;
for (const { onRejected } of this.statesSave) {
onRejected(err);
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onResolved, onRejected) {
if (this.state === 'resolved') {
onResolved(this.internalValue);
} else if (this.$state === 'rejected') {
onRejected(this.internalValue);
}
else {
this.statesSave.push({ onResolved, onRejected });
}
}
}
let p = new NewPromise(resolve => {
// resolve('Hello');
setTimeout(() => resolve('Hello'), 3000);
});
p.then(res => console.log(res));//Hello
这时候控制台就在3s之后输出Hello了
以上就是使用js实现Promise的过程了,部分内容是借鉴网上查找的资料如有雷同请见谅,谢谢