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;