Promise是将异步写法变为同步写法的规范
只是写法的改变,操作并没有改变
异步操作:在回调函数中,一层嵌套一层
同步操作:将方法写在外部
三个状态
pending 表示操作正在执行
resolved 表示操作执行成功
rejected 表示操作执行失败
状态的流向:在Promise中状态有两个方向的流动:
状态由pending流向resolved, 说明操作执行成功完毕
状态由pending流向rejected, 说明操作执行失败完毕
语法: new Promise((resolve, reject) => { 回调函数中执行异步操作 })
如果操作执行成功 执行resolve方法 如果操作执行失败 执行reject方法
在外部通过then方法监听状态的改变
then(success, fail)
该方法接收两个参数
success: 表示成功时候执行的回调函数,参数是由 resolve方法执行的时候传递的参数(只能传递一个)
fail:表示失败时候执行的回调函数,参数是由 reject方法执行的时候传递的参数(只能传递一个)
then方法的返回值是Promise对象,因此,可以链式调用该方法
上一个then方法的输出,将作为下一个then方法参数的输入。如果操作已经执行完毕,then方法也会立即执行
实现Promise:
<script> // 构造函数 function MyPromise(callback) { // 定义当前状态 this.status = 'pending'; // 定义成功时候的回调函数队列 this.successArr = []; // 定义失败时候的回调函数队列 this.failArr = []; // 实现成功时候执行的方法 resolve方法 let resolve = value => {
// this在普通函数中指向window 我们这里使用箭头函数 this的指向永远是定义时的 就解决了this的指向问题
// 改变状态 this.status = 'resolved'; // 依次执行成功队列的方法 this.successArr.forEach(fn => value = fn(value)); // this.successArr.forEach(function(fn) { // value = fn(value); // }) // 将value存储在自身 this.value = value; // 清空队列 this.successArr = []; }; // 实现失败时候执行的方法 let reject = value => { // 更改状态 this.status = 'rejected'; // 执行回调函数 this.failArr.forEach(fn => value = fn(value)); // 将value存储在自身 this.value = value; // 清空队列 this.failArr = []; } // 执行回调函数 try { callback(resolve, reject); } catch(e) { // 运行时出现了错误,也就失败了 reject(e); } }; // 原型then方法 MyPromise.prototype.then = function(success, fail) { // 要是处于执行的pending状态,要存储回调函数 // 判断状态 if(this.status === 'pending') { // 存储 往成功回调函数队列中添加数据 success && this.successArr.push(success); // 如果fail不是undnefined,我们再往失败回调函数队列中添加数据 fail && this.failArr.push(fail); } else if(this.status === 'resolved') { // 立即执行,不需要存储 success && success(this.value); } else { // 失败了 fail && fail(this.value); }; // 返回this return this; }; // 创建promise对象 let p = new MyPromise((resolve, reject) => { console.log('start'); setTimeout(() => { // 如果成功执行resovle resolve('执行成功'); // 如果失败执行reject // reject('执行失败'); }, 1000); }); // 监听结果 p.then( (success) => { console.log('success', success); // 前一个then方法的返回值将作为后一个then方法的参数 return '第一个监听执行成功then方法的返回值'; }, (fail) => { console.log('fail', fail); return '第一个监听失败成功then方法的返回值'; }) // 链式调用 .then((success) => { console.log(success); return '第er个监听执行成功then方法的返回值'; }, (fail) => { console.log(fail); return '第er个监听失败成功then方法的返回值'; }) .then((success) => { console.log(success); return '第三个监听执行成功then方法的返回值'; }, (fail) => { console.log(fail); return '第三个监听失败成功then方法的返回值'; }) </script>