定义
- promise:承诺,许诺
- Promise是异步编程的一种实现方案,比起传统的解决方案(回调函数和事件),更合理,更易于维护,解决了异步回调地狱。
- 一个Promise就是一个对象,它代表了一个异步操作最终完成或者失败。
- Promise对象用于异步操作,它表示一个尚未完成且预计未来完成的异步操作。
JavaScript的异步和回调
- 1、JavaScript的执行环境是单线程的。所谓单线程,就是指JavaScript引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完成后才能执行下个任务,它会阻塞其他任务,这个任务可以成为主线程。但实际上还有其他线程(事件触发线程,ajax请求线程)。
- 2、同步模式。既上述所说的单线程模式,一次只能执行一个任务,函数调用后需要等待函数执行结束并且返回结果,才会去执行下一个函数。如果这个任务执行的时间长,则会阻塞下个任务的执行。
var msg = "this is msg"
while(true)
cosnole.log(msg) // 不会执行
- 3、异步模式。既与同步模式相反,可以一起执行多个任务。setTimeout(()=>{},1000)是典型的异步执行任务。
setTimeout(function() {
console.log('task A');
}, 0);
console.log('task B');
//先输出taskB 在输出taskA
//因为同步任务先于异步任务执行,哪怕定时器的延时时间是0s
- 4、回调函数。在异步任务完成以后,我们需要获取处理后的结果,通常,我们可以将这个函数先定义,存储在内存中,将其当做参数传入之前的异步操作函数中,等异步操作结束,就会调用执行这个函数,这个函数就叫做回调函数(callback)。
function fn(cb) {
var a = 'aa'
setTimeout(() => {
a = 'change a'
cb && cb(a)
}, 1000)
}
fn(function(v){
console.log(v)
})
- 5、在文件读取,资源请求都是异步的,我们都可以通过回调来获取异步的结果,但这样又会造成函数回调层次太深,造成回调地狱。
const fs = require('fs')
fs.readFile('./a.txt',(data,error)=>{
if(data){
fs.readFile('./b.txt',(data,error)=>{
fs.readFile('./c.txt',(data,error)=>{
fs.readFile('./d.txt',(data,error)=>{
fs.readFile('./e.txt',(data,error)=>{
})
})
})
})
}
})
Promise的基本用法
//许下一个承诺
let flag = true
let promise = new Promise((resolve,reject)=>{
if(flag){
reject('error') //失败的回调
}else{
resolve('success') //成功的回调
}
})
// 执行这个承诺 .then
promise.then(data=>{
console.log(data)
}).catch(error=>{
console.log(error)
}).finally(()=>{
console.log('finally')
})
Promise.all
Promise的静态方法,该方法接受一个Promise数组,数组内所有的任务同时执行,只有所有的任务执行完毕才将pending
转换成fulfilled
let pArr = []
let p1 = new Promise((resolve,reject)=>{
})
pArr.push(p1)
let p2 = new Promise((resolve,reject)=>{
})
pArr.push(p2)
Promise.all(pArr).then(()=>{})
Promsie.race
race也是Promise的静态方法,用法与all()类似,也是接收一个Promise数组,不同点是all()方法是等数组中的所有任务同时执行,且所有任务执行完毕才将状态由pedding转为fulfilled,race()方法是数组中的所有任务同时执行,有一个任务执行完毕时,就将状态由pedding转为fulfilled。
手动实现Promise
简易版
function MPromise() {
let cb = arguments[0]
let self = this
this.msg = ''
this.status = 'pending'
cb(
function() {
self.status = 'resolve'
self.msg = arguments[0]
},
function() {
self.status = 'reject'
self.msg = arguments[0]
}
)
}
MPromise.prototype.then = function() {
if (this.status == 'resolve') {
arguments[0](this.msg)
}
if (this.status == 'reject' && arguments[1]) {
arguments[1](this.msg)
}
}
//测试代码
let isFlag = false
let p = new KPromise((resolve, reject) => {
if (isFlag) {
resolve('success')
} else {
reject('error')
}
})
p.then(
data => {
console.log(data)
},
error => {
console.log(error)
}
)
完整版
/* ----------------------------------------------------------------------------
* Promise 完整版
--------------------------------------------------------------------------- */
const states = {
PENDING : 'pending',
FULFILLED: 'fulfilled',
REJECTED : 'rejected'
}
class Promise {
/**
* [ 构造函数 ]
* @param {[Function]} excurtor [执行函数]
* @return {[Undefined]} undefined
*/
constructor (excurtor) {
let self = this;
this.status = states.PENDING; // 当前状态
this.value = undefined; // 成功的内容
this.reason = undefined; // 失败的原因
this.onFulfilled = []; // 存储成功回调
this.onRejected = []; // 存储失败回调
// 成功方法
function resolve (value) {
let onFulfilled = self.onFulfilled;
// 判断状态是否为pending,只有此状态时,才可以发生状态改变
if (self.status === states.PENDING) {
self.status = states.FULFILLED;
self.value = value;
if (onFulfilled.length) {
onFulfilled.forEach(fn => {
fn();
});
}
}
}
// 失败方法
function reject (reason) {
let onRejected = self.onRejected;
// 判断状态是否为pending,只有此状态时,才可以发生状态改变
if (self.status === states.PENDING) {
self.status = states.REJECTED;
self.reason = reason;
if (onRejected.length) {
onRejected.forEach(fn => {
fn()
});
}
}
}
// 立即调用执行函数,并捕获异常
try {
excurtor(resolve, reject);
} catch (e) {
reject(e); // 捕获到执行函数异常后,直接执行失败回调
}
}
/**
* [ 实例方法: then ]
* @param {[Function]} onFulfilled [成功回调]
* @param {[Function]} onRejected [失败及异常回调]
* @return {[Object]} promise2
*/
then (onFulfilled, onRejected) {
// 补全参数,实现往下传递
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error =>{ throw error };
let self = this;
let promise2;
promise2 = new Promise((resolve, reject) => {
// 状态已改变为成功时,则立即执行
if (self.status === states.FULFILLED) {
setTimeout(() => { // 此定时器确保回调方法在异步中执行的,也方便进行promiseA+规范测试
// try catch 用来捕获回调方法中抛出的异常
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
// 状态已改变为失败时,则立即执行
if (self.status === states.REJECTED) {
setTimeout(() => { // 同上
// 同上
try {
let x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
// 处理异步情况,先存在起来,等状态改变再执行相应回调
if (self.status === states.PENDING) {
self.onFulfilled.push(() => {
setTimeout(() => { // 同上
// 同上
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
self.onRejected.push(() => {
setTimeout(() => { // 同上
// 同上
try {
let x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
/**
* [ 实例方法:catch ]
* @param {[Function]} onRejected [失败及异常回调]
* @return {[Object]} promise
*/
catch (onRejected) {
return this.then(null, onRejected);
}
/**
* [ 静态方法(由类调用):all ]
* @param {[Array]} promises [由promise组成的数组]
* @return {[Object]} promise
*/
static all (promises) {
let res = [];
let count = 0;
let length = promises.length;
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
promise.then(
value => {
res[index] = value;
if (++count === length) {
resolve(res);
}
},
reject
);
});
});
}
/**
* [ 静态方法(由类调用)race ]
* @param {[Array]} promises [由promise组成的数组]
* @return {[Object]} promise
*/
static race (promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, reject);
})
});
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 自己不能等待自己的状态改变
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
let called; // 标识位,要么成功,要么失败;
let typeX = typeof x;
// 判断x的类型是否为对象或者函数且不为null
if (x !== null && (typeX === 'object' || typeX === 'function')) {
try {
let then = x.then; // 获取then方法; 此处的try用于防止第三方库中获取值会抛错
if (typeof then === 'function') { // 说明返回的是promise事例
// 执行then方法,并将this指向x
then.call(x, y => {
if (called) return;
called = true;
// 如果返回的还是promise, 则将会继续递归调用
resolvePromise(promise2, y, resolve, reject);
}, e => {
if (called) return;
called = true;
reject(e);
});
} else { // x为变通对象时,直接成功
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
// 为了方便promiseA+规范测试
Promise.defer = Promise.deferred = function () {
let dtd = {};
dtd.promise = new Promise((resolve, reject) => {
dtd.resolve = resolve;
dtd.reject = reject;
});
return dtd;
};
module.exports = Promise;
// 测试例子 ---------------------------------------------------------------------
let promise = new Promise((resolve, reject) => {
resolve(1000);
//reject(100);
});
promise
.then(
value => {
console.log('then:', value);
return new Promise((resolve, reject) => {
//resolve(199);
reject('error123');
});
},
reason => console.log(`fail: ${ reason }`)
)
.then(
value => console.log(value),
reason => console.log(`fail: ${ reason }`)
);
Promise.all([
new Promise((resolve, reject) => {
resolve(1);
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
}, 1000);
}),
new Promise((resolve, reject) => {
resolve(3);
//reject('出错了')
})
]).then(
value => console.log(value),
e => console.log(e)
);