为什么要用promise
- 指定回调函数的方式更加灵活
- 旧的:必须在启动异步操作前指定
- promise:启动异步任务 => 返回promise对象 => 给promsie对象
- 支持链式调用,可以解决回调地域的问题
- 回调地狱: 回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件
- 回调地狱的缺点:不便于阅读/不便于异常处理
- 解决方案:promise链式调用
- 终极解决方案:async/await
如何使用Promise
API
- Promise 构造函数:Promise(excutor){}
- excutor函数: 执行器(resolve,reject) => {}
- resolove函数: 内部定义成功时,调用 value => {}
- reject函数,内部定义失败,调用 reason => {}
- 说明:excutor会在Promise内部立即回调,异步操作在执行器中执行
- Promise.prototype.then 方法:(onResolved,onRejected) => {}
- onResolved函数:成功的回调函数(value) => {}
- onRejected函数:失败的回调函数(reason) => {}
- 说明:指定用于得到成功value的成功回调和用于得到失败的回调返回一个新的Promise
- Promise.prototype.catch方法: (onRejected) => {}
- onRejected函数。失败的回调函数(reason) => {}
- 说明:then()的语法糖,相当于:then(undefined,onRejected)
- Promise.resolve方法:(value) => {}
- value:成功的数据或promise对象
- 说明:返回一个成功/失败的promise对象
- Promise.reject方法:(reason) => {}
- reason:失败的原因
- 说明:返回一个失败的promise对象
- Promise.all方法:(promise) => {}
- promise:包含n个promise的数组
- 说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败就直接失败
- Promise.race方法:(promise) => {}
- promises: 包含n个promise的数组
- 说明:返回一个新的promise,第一个完成的promose的结果状态就是最终的结果状态
function Promise(executor) {
this.PromiseState = 'pending';
this.PromiseResult = null;
this.callbacks = []
const self = this;
function resolve(data) {
if (self.PromiseState !== 'pending') return;
self.PromiseState = 'fulfilled';
self.PromiseResult = data;
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(data)
});
});
}
function reject(data) {
if (self.PromiseState !== 'pending') return;
self.PromiseState = 'rejected';
self.PromiseResult = data;
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected(data)
});
});
}
try {
executor(resolve, reject);
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function(onResolved, onRejected) {
const self = this;
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value;
}
return new Promise((resolve, reject) => {
function callback(type) {
try {
let result = type(self.PromiseResult);
if (result instanceof Promise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
callback(onResolved);
});
}
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onRejected);
})
}
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function() {
callback(onResolved);
},
onRejected: function() {
callback(onRejected);
}
});
}
})
}
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected);
}
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(v => {
resolve(v)
}, r => {
resolve(r)
})
} else {
resolve(value);
}
})
}
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
Promise.all = function(promises) {
return new Promise((resolve, reject) => {
let count = 0;
let arr = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
count++;
arr[i] = v;
if (count === promises.length) {
resolve(arr);
}
}, r => {
reject(r)
})
}
});
}
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
resolve(v)
}, r => {
reject(r)
})
}
});
}