1、Promise的含义:
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,是能够解决回调地狱的一种方式。
Promise的两个特性:
- 对象的状态不会受外界影响,它的状态值由异步函数的结果决定;
- 对象的状态值一旦确定将不会改变,并且任何时候都能获取,Promise状态的改变,状态值由pending变为resolved或者rejected;
Promise的三个缺点:
- Promise构造函数一旦创建便会立即执行,中途无法取消;
- Promise如果没有设置回调函数,内部发生错误时无法传递到函数外部,外部(异步)函数会继续执行;
- Promise的状态值为pending时,是无法判断目前执行到哪一个阶段,是刚开始执行还是即将结束。
Promise的基本用法:
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise.prototype.then()方法
Promise 实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。
如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。
手写简易版Promise:
const PENDING = 'pending',
RESOLVED = 'resolved',
REJECTED = 'rejected';
function MyPromise(fn){
const that = this;
that.state = PENDING;
that.value = null;
that.resolveCallback = [];
that.rejectCallback = [];
function resolve(value){
if(that.state = PENDING){
that.state = RESOLVED;
that.value = value;
that.resolveCallback.map(cb => cb(that.value));
}
}
function reject(value){
if(that.state = PENDING){
that.state = REJECTED;
that.value = value;
that.rejectCallback.map(cb => cb(that.value));
}
}
try {
fn(resolve, reject);
}catch(err){
reject(err);
}
}
MyPromise.prototype.then = function(onResolved, onRejected){
const that = this;
onResolved = typeof onResolved === 'Function' ? onResolved : v => v;
onRejected = typeof onRejected === 'Function' ? onRejected : r => {
throw r;
};
if(that.state === PENDING){
that.resolveCallback.push(onResolved);
that.rejectCallback.push(onRejected);
}
if(that.state === RESOLVED){
onResolved(that.value)
}
if(that.state === REJECTED){
onRejected(that.value)
}
}