1.什么是Promise?
Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一
2.对于几种常见异步编程方案
- 回调函数
- 事件监听
- 发布/订阅
- Promise对象
这里就拿回调函数说说
1.对于回调函数 我们用Jquery的ajax获取数据时 都是以回调函数方式获取的数据
$.get(url, (data) => {
console.log(data)
)
2.如果说 当我们需要发送多个异步请求 并且每个请求之间需要相互依赖 那这时 我们只能 以嵌套方式来解决 形成 "回调地狱"
$.get(url, data1 => {
console.log(data1)
$.get(data1.url, data2 => {
console.log(data1)
})
})
这样一来,在处理越多的异步逻辑时,就需要越深的回调嵌套,这种编码模式的问题主要有以下几个:
- 代码逻辑书写顺序与执行顺序不一致,不利于阅读与维护。
- 异步操作的顺序变更时,需要大规模的代码重构。
- 回调函数基本都是匿名函数,bug 追踪困难。
- 回调函数是被第三方库代码(如上例中的 ajax )而非自己的业务代码所调用的,造成了 IoC 控制反转。
Promise 处理多个相互关联的异步请求
1.而我们Promise 可以更直观的方式 来解决 "回调地狱"
const request = url => {
return new Promise((resolve, reject) => {
$.get(url, data => {
resolve(data)
});
})
};
// 请求data1
request(url).then(data1 => {
return request(data1.url);
}).then(data2 => {
return request(data2.url);
}).then(data3 => {
console.log(data3);
}).catch(err => throw new Error(err));
2.相信大家在 vue/react 都是用axios fetch 请求数据 也都支持 Promise API
import axios from 'axios';
axios.get(url).then(data => {
console.log(data)
})
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中
3.Promise使用
1.Promise 是一个构造函数, new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数, excutor有两个函数类型形参resolve reject
const promise = new Promise((resolve, reject) => {
// 异步处理
// 处理结束后、调用resolve 或 reject
});
2.promise相当于一个状态机
promise的三种状态
- pending
- fulfilled
- rejected
1.promise 对象初始化状态为 pending
2.当调用resolve(成功),会由pending => fulfilled
3.当调用reject(失败),会由pending => rejected
注意promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变
3.promise对象方法
1.then方法注册 当resolve(成功)/reject(失败)的回调函数
// onFulfilled 是用来接收promise成功的值
// onRejected 是用来接收promise失败的原因
promise.then(onFulfilled, onRejected);
then方法是异步执行的
2.resolve(成功) onFulfilled会被调用
const promise = new Promise((resolve, reject) => {
resolve('fulfilled'); // 状态由 pending => fulfilled
});
promise.then(result => { // onFulfilled
console.log(result); // 'fulfilled'
}, reason => { // onRejected 不会被调用
})
3.reject(失败) onRejected会被调用
const promise = new Promise((resolve, reject) => {
reject('rejected'); // 状态由 pending => rejected
});
promise.then(result => { // onFulfilled 不会被调用
}, reason => { // onRejected
console.log(rejected); // 'rejected'
})
4.promise.catch
在链式写法中可以捕获前面then中发送的异常
promise.catch(onRejected)
相当于
promise.then(null, onRrejected);
// 注意
// onRejected 不能捕获当前onFulfilled中的异常
promise.then(onFulfilled, onRrejected);
// 可以写成:
promise.then(onFulfilled)
.catch(onRrejected);
4.promise chain
promise.then方法每次调用 都返回一个新的promise对象 所以可以链式写法
function taskA() {
console.log("Task A");
}
function taskB() {
console.log("Task B");
}
function onRejected(error) {
console.log("Catch Error: A or B", error);
}
var promise = Promise.resolve();
promise
.then(taskA)
.then(taskB)
.catch(onRejected) // 捕获前面then方法中的异常
5.Promise的静态方法
1.Promise.resolve 返回一个fulfilled状态的promise对象
Promise.resolve('hello').then(function(value){
console.log(value);
});
Promise.resolve('hello');
// 相当于
const promise = new Promise(resolve => {
resolve('hello');
});
2.Promise.reject 返回一个rejected状态的promise对象
Promise.reject(24);
new Promise((resolve, reject) => {
reject(24);
});
3.Promise.all 接收一个promise对象数组为参数
const p1 = new Promise((resolve, reject) => {
resolve(1);
});
const p2 = new Promise((resolve, reject) => {
resolve(2);
});
const p3 = new Promise((resolve, reject) => {
reject(3);
});
Promise.all([p1, p2, p3]).then(data => {
console.log(data); // [1, 2, 3] 结果顺序和promise实例数组顺序是一致的
}, err => {
console.log(err);
});
4. Promise 代码自己实现
// 自己实现Promise类
function Promise(executor) {
// 定义一个状态 表示当前promise状态
let _this = this;
_this.status = "pending"; // 默认promise状态是等待态
_this.value = undefined;
_this.reason = undefined;
// 存放所有成功的回调
_this.onResolvedCallbacks = [];
// 存放所有失败的回调
_this.onRejectedCallbacks = [];
function resolve(value) {
// 只能从等待态变成功态
if (_this.status === "pending") {
_this.status = "fulfilled";// 状态变为成功态
_this.value = value;
_this.onResolvedCallbacks.forEach(fn => fn());
}
}
function reject(reason) {
// // 只能从等待态变失败态
if (_this.status === "pending") {
_this.status = "rejected"; // 状态变为失败态
_this.reason = reason;
_this.onRejectedCallbacks.forEach(fn => fn());
}
}
//可能执行excecute时候报错
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
// 这个函数的作用主要就是判断x 是不是普通的值还是promsie
// 然后返回对应的成功状态或者失败状态进行传递值
function resolvePromise(promise2, x, resolve, reject) {
//判断promise 是否等于自身
if (x === promise2) {
return reject(new TypeError("循环引用"));
}
if (x != null && typeof x === 'object' || typeof x === "function") {
// 可能是promise
try { //定义变量把then取出来
let then = x.then; // then属性有可能会抛异常
if (typeof then === "function") {
// 认为是一个promise
//then.call确保then指向返回的promise 然后是成功或者失败
then.call(x, (y) => {
resolve(y)
}, (r) => {
reject(r);
});
} else {
//x 是一个普通的d对象值
resolve(x);
}
} catch (e) {
reject(e);
}
} else {
// 不是引用类型 普通值 12 "avc"
resolve(x);
}
}
// 定义then方法
Promise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : data => data;
onRejected = typeof onRejected === 'function' ? onRejected : reson => { throw reson };//reson => { throw reson }
let _this = this;
// then被执行 需要再次返回一个新的promise实例
// 需要拿到当前then方法 成功或者失败的结果
let promise2 = new Promise(function (resolve, reject) {
if (_this.status === "fulfilled") {
setTimeout(() => {
// 需要使用到promise2 放入异步中
try {
let x = onFulfilled(_this.value);
//resolve(x);
// 对x进行判断
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (_this.status === "rejected") {
setTimeout(() => {
try {
let x = onRejected(_this.reason);
// 对x进行判断
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
}
if (_this.status === "pending") {
_this.onResolvedCallbacks.push(function () {
setTimeout(() => {
try {
let x = onFulfilled(_this.value);
// 对x进行判断
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
_this.onRejectedCallbacks.push(function () {
setTimeout(() => {
try {
let x = onRejected(_this.reason);
// 对x进行判断
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
// 导出该构造函数
module.exports = Promise;