1. 为何产生promise?
- 相信大家在写JS的时候写过回调函数,当写了多层回调的时候,逻辑已经很难理清楚了,这就是promise解决的问题: 回调地狱
- 多层嵌套的回调中,有同步/异步的方法,那么执行顺序会混乱,而promise采用链式调用。
2. 什么是promise?
-
所谓promise, 翻译成中文为“承诺, 诺言”, 比如, 你承诺这个月挣钱了给你老婆买一个包, 那么你先去挣钱, 等挣钱了就立刻给老婆买包,实现你的诺言,没挣到钱就立马道歉。换成代码就是:
// 先许下承诺 const geilaopomaibao = new Promise((resolve, reject) => { // 开始挣钱了 if (money) { // 挣到了 reslove('10k'); } else { // 没挣着钱 reject('因为没发工资,这个月没挣到钱'); } }) // 不管挣没挣到钱,要给老婆一个交代。 geilaopomaibao.then( res => { // res就是挣到的钱 maibao(res); }, reason => { // 道歉 // reason 就是理由 } );
-
promise是一种规范,也就是大家都可以实现自己的promise,只要遵循规范,都是可以的。在ES6中也正式引入了promise,当然还有很多库去实现了promise规范,列如: Q,bluebird
规范:
Promises/A+
Promises/A+ 中文
3. 如何使用promise?
- 首先来个简单的列子: <br/>
```
const task = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功');
}, 3000);
})
task.then((res) => {
// 3秒后打印成功
console.log(res);
})
```
看这个列子似乎没什么特别之处,感觉就是把callback换成resolve, 那么再看看下面一个
```
// 获取列表之前,需要先判断是否登录,then的链式调用
new Promise((resolve, reject) => {
$.ajax('/api/user/login', {
success: function(isLogin) {
if (isLogin) {
resolve(data);
} else {
reject('没有登录');
}
}
})
}).then(
res => {
$.ajax('/api/list', {
success: function(data) {
resolve(data);
}
})
},
reason => {
alert(reason)
}
).then((data) => {
// data为list数据
// 在这里还可以为list排序
return data.sort();
}).then((list) => {
// 好了,这里的拿到list 可以使用了
})
```
- promise有几个静态方法,无需实例化既可使用;
1. Promise.all() (传入一个promise数组, 等待所有代码完成, 或第一个代码失败)
```
const task1 = {ji: 2018};
const task2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('2018年');
}, 5000);
});
const task3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('新年好');
}, 2000);
});
Promise.all([task1, task2, task3]).then(values => {
console.log(values);
// 5秒后打印 [{ji: 2018}, '2018年', '新年好']
});
```
2. Promise.race() (传入一个promise数组,当其中一个完成或失败,则采用该promise值)
```
const task2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('2018年');
}, 5000);
}); ;
const task3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('新年好');
}, 2000);
});
Promise.race([task1, task2, task3]).then(values => {
console.log(values);
// 2秒后打印 '新年好'
});
```
3. Promise.resolve() (传入一个值,返回一个同步执行成功状态的promise, 适用于: 如果有方法要求返回一个promise, 但你已经有一个值了, 则这个时候使用)
```
/**
* @param {Promise} fn 需要传入一个promise对象
*/
const task = (fn) => {
fn.then()
// ........
}
Promise.resolve(1);
```
4. Promise. reject() (传入一个值,返回一个同步执行的失败状态的promise)
4. 实现一个promise
class Promise {
constructor(task) {
// 当前状态 存在 { pending fulfilled rejected } 3种状态
this.status = 'pending';
// 当resolve时的数据
this.resolveData = null;
// 当reject时的数据
this.rejectData = null;
// 存放所有回调 实现同步调用
this.onFulfilledList = [];
this.onRejectedList = [];
// 执行传入任务
try {
task(this.onResolve.bind(this), this.onReject.bind(this));
} catch (e) {
this.onReject(e);
}
}
/**
* 成功,通过
*
* @param {any} data resolve数据
*/
onResolve(data) {
if (this.status === 'pending') {
this.status = 'fulfilled';
this.resolveData = data;
this.onFulfilledList.forEach(fn => {
fn(this.resolveData);
})
}
}
/**
* 拒绝,失败
*
* @param {any} data reject数据
*/
onReject(data) {
if (this.status === 'pending') {
this.status = 'rejected';
this.rejectData = data;
this.onRejectedList.forEach(fn => {
fn(this.rejectData);
})
}
}
/**
* 回调
*
* @param {function} onFulfilled 成功回调
* @param {function} onRejected 失败回调
* @return {*}
*/
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = () => {};
}
if (typeof onRejected !== 'function') {
onRejected = () => {};
}
let promise2;
switch (this.status) {
case 'pending':
promise2 = new Promise((resolve,reject) => {
this.onFulfilledList.push(() => {
let x = onFulfilled(this.resolveData);
this.resolvePromise(promise2, x, resolve, reject);
});
this.onRejectedList.push(() => {
let x = onRejected(this.rejectData);
this.resolvePromise(promise2, x, resolve, reject);
});
});
break;
case 'fulfilled':
promise2 = new Promise((resolve, reject) => {
let x = onFulfilled(this.resolveData);
this.resolvePromise(promise2, x, resolve, reject);
});
break;
case 'rejected':
promise2 = new Promise((resolve, reject) => {
let x = onRejected(this.rejectData);
this.resolvePromise(promise2, x, resolve, reject);
});
break;
default:
throw 'promise status error';
}
return promise2;
}
/**
* catch方法 等于 reject
*
* @param onRejected
*/
catch(onRejected) {
if (typeof onRejected !== 'function') {
onRejected = () => {};
}
let promise2;
promise2 = new Promise((resolve, reject) => {
let x = onRejected(this.rejectData);
this.resolvePromise(promise2, x, resolve, reject);
});
}
/**
* 递归方法,多次then
*
* @param {Promise} promise2 第二个promise
* @param {any} x 上一次then所返回的数据
* @param {function} resolve 当前的成功方法
* @param {function} reject 当前的失败方法
* @return {*}
*/
resolvePromise(promise2, x, resolve, reject) {
// 第二个then方法
let then;
// 如果x 等于 promise2 重复调用
if(promise2 === x){
return reject(new TypeError('循环引用'));
}
if (x instanceof Promise) {
if(x.status === 'pending'){
x.then(function(y){
resolvePromise(promise2, y, resolve, reject);
}, reject);
} else if (x.status === 'fulfilled'){
resolve(x.resolveData);
} else if (x.status === 'rejected'){
reject(x.rejectData);
}
} else if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
// 取出下一次then方法
then = x.then;
// 如果then为fn 递归调用then方法
if (typeof then == 'function') {
then.call(x, function (y) {
resolvePromise(promise2, y, resolve, reject)
}, reject);
} else {
// 如果then 不为fn 则以x为值fulfill promise
resolve(x);
}
} catch (e) {
reject(e);
};
} else {
resolve(x);
}
}
/**
* all方法 传入数组,等待所有promise完成
* 1. 如果有一个为reject,则返回reject
*
* @param {Array} promiseList 需要执行的数组
* @return {Promise}
*/
static all(promiseList) {
// 如果传入不是数组,抛出错误
if (!Array.isArray(promiseList)) {
new TypeError('must be an array');
}
return new Promise((resolve, reject) => {
// 如果传入数组长度为0 则直接resolve
if (promiseList.length === 0) {
resolve([]);
}
const allData = new Array();
let resI = 0;
promiseList.forEach((item, index) => {
if (item instanceof Promise) {
item.then(
res => {
allData[index] = res;
resolveAll();
},
rej => {
reject(rej);
}
)
} else {
allData[index] = item;
resolveAll();
}
})
function resolveAll() {
resI++;
if (resI === promiseList.length) {
resolve(allData);
}
}
});
}
/**
* race 方法 当某一个promise完成,则返回
*
* @param {Array} promiseList 需要执行的数组
* @return {Promise}
*/
static race(promiseList) {
// 如果传入不是数组,抛出错误
if (!Array.isArray(promiseList)) {
new TypeError('must be an array');
}
return new Promise((resolve, reject) => {
// 如果传入数组长度为0 则直接resolve
if (promiseList.length === 0) {
resolve([]);
}
promiseList.forEach(item => {
promiseList.forEach(item => {
if (item instanceof Promise) {
item.then(
res => {
resolve(res);
},
rej => {
reject(rej);
}
)
} else {
resolve(item);
}
})
})
})
}
/**
* resolve方法
*
* @param value
* @return {Promise}
*/
static resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(res => {
resolve(res);
})
} else {
resolve(value);
}
})
}
/**
* reject方法
*
* @param reason
* @return {Promise}
*/
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
}
网友评论