Promise 简单理解:
promise 是对某人某事做许诺, 无论多久无论多远, 这个承诺肯定会实现, 或许会是成功, 或许会是失败, 但肯定会得到结果.
Promise 有三种状态
-
pending 初始状态
-
fullfilled 成功后的状态
-
rejected 失败的状态
!! 状态转变规则: 只能由 pending 变为 fullfilled 或 rejected, 且在状态改变后不能再次改变.
Promise 是种异步流程的控制手段
Promise 可以解决类似 ajax 的异步回调地狱问题, Promise 采用了链式调用来解决上述问题, 且支持多个并发请求, Promise 的 then 方法是异步的, 但 Promise 本身不是异步.
promise.then().then().then()
1, 简单理解三种状态
- 只有 pending 状态时可以改变状态; 状态发生改变后不可再次改变; Promise 实例上有个 then 方法, 可以接收两个参数(成功和失败函数); Promise 在发生错误时会直接执行失败函数, 并变为失败状态;
const primise = new Promise((resolve, reject) => { // 默认 promise 中的excutor是同步执行的。
resolve('成功');
reject('失败');
}
promise.then(data => {
console.log('success');
}, err => {
console.log('failed');
}));
2, promise 链式调用解决 ajax 回调地狱
ajax 回调 demo:
```js
// ajax 1次
$.ajax(
...,
success() {
// ajax 2次
$.ajax(
...,
success() {
......
// ajax n 次
}
)
}
)
```
Promise 链式调用:
-
如果 promise 返回的是 Promise 对象, 则成功和失败函数中会获取这个 Promise 的结果, 如果是成功状态就会执行外层 promise 的 resolve 方法, 并将数据传入该函数, 反之会传入 reject 函数.
-
promise 实现链式调用返回的不是 this 对象, 而是新的 Promise 对象.
$fn(param, callback)
function ajax(param){
return new Promise((resolve, reject) => {
$fn(param, function(err, data){
if(err) reject(err);
resolve(data);
}
}
}
ajax(param).then(data => {
return ajax(data); // 返回新的 Promise 对象
/* return 200; // 返回了普通的值, 会走下个 then 中的 resolve 方法
throw new Error(); // 发生错误时会走下个 then 中的 reject 方法.
*/
}).then(data => {
return ajax(data);
}, err => {
console.log(err);
}).then(data => {
return ajax(data);
}).then(data => {
return ajax(data);
}).catch(err){
// 也可以集中处理错误;
};
// 即使 promise 中有失败, 也可以继续 then.
3, Promise 的其他常用方法:
① Promise.all 处理并发的请求, 并在全都处理成功时变为 fullfilled 状态, 如果其中有发生错误,则状态立即变为 reject 状态.
$fn(param, callback)
function ajax(param){
return new Promise((resolve, reject) => {
$fn(param, function(err, data){
if(err) reject(err);
resolve(data);
}
}
}
Promise.all([ajax('1'), ajax('2')]).then((r1,r2)=>{
console.log(r1,r2);
},err=>{
console.log(err);
});
② Promise.race 处理多个并发请求, 执行顺序不确定, 但只在最快的请求完成时改变状态.
$fn(param, callback)
function ajax(param){
return new Promise((resolve, reject) => {
$fn(param, function(err, data){
if(err) reject(err);
resolve(data);
}
}
}
Promise.race([ajax('1'), ajax('2')]).then((r1,r2)=>{
console.log(r1,r2);
},err=>{
console.log(err);
});
③ Promise.resolve() 返回成功状态的 Promise Promise.reject() 返回失败状态的 Promise
Promise.resolve('success').then(data => {
console.log('data') //success
});
Promise.reject('fail').then(data => {
console.log(data); //fail
});
手动实现 Promise
promisify
// 基础版本
class Promise{
// 构造器
constructor(executor) {
// 初始化状态
this.state = 'pending';
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
// 成功
const resolve = value => {
if (this.state === 'pending') {
// 执行成功后改变状态
this.state = 'fullfilled';
// 保存成功的值
this.value = value;
}
};
// 失败
const reject = reason => {
if (this.state === 'pending') {
// 执行失败后改变状态
this.state = 'rejected';
// 保存失败的原因
this.reason = reason;
}
};
// 立即执行, 如果有错误直接执行 reject
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
};
// 完善 then 方法
class Promise{
// 构造器
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fullfilled';
this.value = value;
}
};
const reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
// then 方法 有两个参数(onFulfilled onRejected)
then(onFulfilled, onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.state === 'fulfilled') {
onFulfilled(this.value);
} else if (this.state === 'rejected') {
// 状态为rejected,执行onRejected,传入失败的原因
onRejected(this.reason);
};
}
};
// 完善异步方法
class Promise{
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
// 成功存储的数组
this.onResolvedCallbacks = [];
// 失败存储的数组
this.onRejectedCallbacks = [];
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fullfilled';
this.value = value;
// resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
// resolve执行,调用成功数组的函数
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value);
} else if (this.state === 'rejected') {
onRejected(this.reason);
};
// 当状态state为pending时
if (this.state === 'pending') {
// onFulfilled传入到成功数组
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value);
});
// onRejected传入到失败数组
this.onRejectedCallbacks.push(() => {
onRejected(this.value);
});
}
}
};
// 完善链式调用
class Promise{
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
// 成功存储的数组
this.onResolvedCallbacks = [];
// 失败存储的数组
this.onRejectedCallbacks = [];
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fullfilled';
this.value = value;
// resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
// resolve执行,调用成功数组的函数
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
// 返回新的 Promise 对象
const newPromise = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
const fullfilled = onFulfilled(this.value);
// Promise A+ 规范规定: 让不同的promise代码互相套用,叫做resolvePromise
resolvePromise(newPromise, fullfilled, resolve, reject);
} else if (this.state === 'rejected') {
onRejected(this.reason);
};
// 当状态state为pending时
if (this.state === 'pending') {
// onFulfilled传入到成功数组
this.onResolvedCallbacks.push(() => {
const fullfilled = onFulfilled(this.value);
// Promise A+ 规范规定: 让不同的promise代码互相套用,叫做resolvePromise
resolvePromise(newPromise, fullfilled, resolve, reject);
});
// onRejected传入到失败数组
this.onRejectedCallbacks.push(() => {
const rejected = onRejected(this.value);
// Promise A+ 规范规定: 让不同的promise代码互相套用,叫做resolvePromise
resolvePromise(newPromise, rejected, resolve, reject);
});
}
});
return newPromise;
}
};
/* 完整的 Promise */
// 1. 实现 Promise 类
class Promise {
constructor(executor) {
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (data) => {
if (this.status === 'pending') {
this.status = 'resolved';
this.value = data;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = (data) => {
if (this.status === 'pending') {
this.status = 'rejected';
this.reason = data;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
// onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : y => y;
// onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
if (typeof onFulfilled !== 'function') {
y => y;
}
if (typeof onRejected !== 'function') {
err => { throw err };
}
let newPromise;
if (this.status === 'pending') {
newPromise = new Promise((resolve, reject) => {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
const fullfilled = onFulFilled(this.value);
resolvePromise(newPromise, fullfilled, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// 存储失败回调
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let rejected = onRejected(this.reason);
resolvePromise(newPromise, rejected, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
});
}
if (this.status === 'resolved') {
newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try {
const fullfilled = onFulFilled(this.value);
resolvePromise(newPromise, fullfilled, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
if (this.status === 'rejected') {
newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let rejected = onRejected(this.reason);
resolvePromise(newPromise, rejected, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
// 调用 then 方法返回新的 Promise
return newPromise;
}
// catch Promise 中的错误信息
catch(onRejected) {
// catch 就是 then 失败时的简写
return this.then(null, onRejected);
}
}
// 2, 官方给出的 resolvePromise 函数, 用来验证 Promise 类
/*
* 如果 then 是 function, 调用 x 作为传入的 this, 第二个参数 resolvePromise 为:
* 如果/当 resolvePromise 被值 y 调用时, 就执行 [[Resolve]](promise, y);
* 如果/当 rejectPromise 被 r 作为拒绝原因调用时, 就执行 reject 并 抛出异常 r;
* 如果/当 resolvePromise 和 rejectPromise 都被调用, 或相同的参数导致多次调用时, 只有第1个调用生效, 其他调用将被忽略
* 如果调用 then 抛出异常了,
* 如果调用了 resolvePromise 或 rejectPromise, 调用将被忽略;
* 否则 promise 状态变为 reject, 并抛出异常信息 e
*/
function resolvePromise(newPromise, x, resolve, reject) {
if (newPromise === x) {
return reject(new TypeError('循环调用'));
}
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let called;
try {
// 防止取 then 时出现异常 Object.defineProperty
const { then } = x; // 取x的then方法 {then:{}}
if (then === 'function') { // 如果then是函数就认为这是promise
// call 的第1个参数是this ,后面的参数是成功的回调和失败的回调
then.call(x, y => { // 成功的回调
// 如果y是promise就继续递归解析promise
if (called) return;
called = true;
resolvePromise(newPromise, y, resolve, reject);
}, r => { // 失败的回调
if (called) return;
called = true;
reject(r);
});
} else {
// then 是普通值
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x); // x 就是个普通值
}
}
// 3, Promise的常用方法
// 生成成功的promise
Promise.resolve = (value) => {
return new Promise((resolve, reject) => resolve(value));
}
// 生成失败的promise
Promise.reject = (reason) => {
return new Promise((resolve, reject) => reject(reason));
}
// Promise.race 方法, 返回多个 promise 中结果最快的那个, 无论本身的状态是成功还是失败
Promise.race = (promises) => {
return new Promise((resolve, reject) => {
const length = promises.length;
for (let i = 0; i < length; i++) {
promises[i].then(resolve, reject);
}
})
}
// Promise.all,该方法的作用是将多个 Promise 对象实例包装,生成并返回1个新的 Promise 实例。
Promise.all = (promises) => {
return new Promise((resolve, reject) => {
const length = promises.length;
const arr = [];
let i = 0; // 为了保证获取到全部的成功给每个 Promise 加上个索引
function process(index, data) {
arr[index] = data;
i++;
if (i === length) {
resolve(arr);
}
}
for (; i < length; i++) {
promises[i].then(resolve => {
process(i, resolve);
}, reject);
}
});
}
// Promise.deferred, 异步模式
Promise.deferred = function () {
const deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
})
return deferred;
}
// 4, 导出模块
module.exports = Promise;
// 5, 测试代码, 安装模块:npm install promises-aplus-tests -g 执行命令:promises-aplus-tests 文件名,即可得到结果