深度学习Promise a+ 规范
Promise A+ 规范
Promise表示一个异步操作的最终结果。与Promise最主要的交互方法是通过将函数传入它的then方法从而获取得Promise最终的值或Promise最终最拒绝(reject)的原因。
术语
promise
是一个包含了兼容promise规范then方法的对象或函数
thenable
是一个包含了then方法的对象或者函数
value
是任何JavaScript值
execption
是有throw
表达式抛出来的值
reason
是一个用于描述Promise被拒绝的原因
要求
Promise 是一个类 无需考虑兼容问题
当使用promise时 有一个执行器 executor 会立即执行
promise有三个状态,pendding
,rejected
,fulfilled
。
定义状态
一个promise必须处在其中之一的状态
- 如果是pendding状态 则promise 可以转换到fulfilled或者rejected状态
- 如果是fulfill状态,则promise不能转换成任何状态,而且必须有一个值
- 如果是rejected状态,则promise不能转换成任何状态,而且必须有一个原因
const PEDDING = "PEDDING";
const REJECTED = "REJECTED";
const FULFILLED = "FULFILLED";
Promise的基本代码结构
value
表示成功的值
reason
表示被拒绝的原因
executor
new Promise接受一个立即执行函数, resolve
,reject
作为其参数
class Promise {
constructor(executor) { // new Promise 接受一个执行器
this.value = undefined; // 成功的值
this.reason = undefined; // 失败的值
const resolve = (value) => {
// 如果是pendding状态 则promise 可以转换到fulfilled或者rejected状态
if (this.status === PEDDING) {
this.value = value;
this.status = FULFILLED; // 把状态置成 FULFILLED
}
};
const reject = (reason) => {
// 如果是pendding状态 则promise 可以转换到fulfilled或者rejected状态
if (this.status === PEDDING) {
this.reason = reason;
this.status = REJECTED; // 把状态置成 REJECTED
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
// ....
}
then 方法
一个Promise必须提供一个then方法来获取其值或原因。
promise.then(onFulfilled, onRejected)
规范
onFulfilled
和onRejected
都是可选参数。如果onFulfilled不是一个函数,则可以忽略;如果onRejected不是一个函数,也可以进行忽略- 如果onFulfilled是一个函数, 它必须在
promise
fulfilled 之后调用, 且promise
的value是它的第一个参数; 它不能在promise
fulfilled之前调用,而且只能调用一次 - 如果onRejected是一个函数,它必须在
promise
rejected 之后调用,且promise
的reason是它的第一个参数, 它也不能在promise
rejected之前调用,并且也只能调用一次。 onFulfilled
和onRejected
值允许在execution contet栈仅包含平台代码时运行。onFulfilled
和onRejected
必须被当做函数调用。- 一个promise,它的then方法可以多次调用,
- 当
promise
fulfilled后,所有onFulfilled都必须按照其注册顺序执行 - 当
promie
rejected 后,所有onRejected也都必须按照其之策顺序执行
- 当
then
必须返回一个promise
promise2 = promise1.then(onFulfilled,onRejected)
constructor(){
// ....
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
// 如果是pendding状态 则promise 可以转换到fulfilled或者rejected状态
if (this.status === PEDDING) {
this.value = value;
this.status = FULFILLED; // 把状态置成 FULFILLED
this.onFulfilledCallbacks.forEach((fn) => fn()); // 按注册时的顺序执行
}
};
const reject = (reason) => {
// 如果是pendding状态 则promise 可以转换到fulfilled或者rejected状态
if (this.status === PEDDING) {
this.reason = reason;
this.status = REJECTED; // 把状态置成 REJECTED
this.onRejectedCallbacks.forEach((fn) => fn()); // 按注册时的顺序执行
}
};
}
//
then(onFulfilled, onRejected) {
// 1. then方法接受两个参数
// 验证onFulfilled 和 onRejected 的类型
// 5 onRejected 和 onFulfilled 必须当做函数调用
// 值穿透
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejected = typeof onRejected === "function" ? onRejected : (v) => {throw v};
// 实现链式调用
let promise2 = new Promise((resolve, reject) => {
// 订阅方法
if (this.status === FULFILLED) {
// 2 onFulfilled 必须在 promise fulilled之后调用。 且promise的value是其第一个参数
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// 7.1 此时x可能是一个promise, 如果是promise 需要看一下promise是成功还是失败。 .then, 如果成功则吧
// 成功的结果调用promise2的resolve传递进去, 失败则同理
// 总结 x的值 决定是调用promise2的resolve还是reject, 如果是promise,则取他的状态,如果是普通值
// 就直接调用resolve
resolvePromise(promise2, x, resolve, reject); // 解析promise流程
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
// 3 onRejected 必须 在reject之后调用 , 且promise的reason为它的第一个参数
// 失败调用失败的方法
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
-
// 4 onRejected 和 onFulfilled只允许在 execution context 栈 仅包含你平台代码时运行
if (this.status === PEDDING) {
// 6.1 把onFulfilled 缓存起来, 当resolve时 按照其添加顺序执行
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// 6.2 把onRejected 缓存起来 在调用reject时再按照其添加顺序执行
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
// 7. then 必须返回一个promise
return promise2;
}
promise解析流程
/**
* promise解析过程: 是一个以promise和一个值作为参数的抽象过程, 可以表示为[[Resolve]](promise,x)
* 1. 如果promise和x的值指向同一个值, 使用TypeError作为原因将promise拒绝
* 2. 如果x是一个promise 则采用其状态
* 1. 如果x是pendding状态,promise必须保持pendding走到x fulfilled或者rejected
* 2. 如果x是fulfilled状态,将x的值用于fulfilled promise
* 3. 如果x是rejected状态,将x的值用于reject promise
* 3. 如果x是一个对象或者一个函数
* 1. 将then赋值x.then
* 2. 如果在取x.then值时抛出了异常, 则以这个异常为原因将promise拒绝
* 3. 如果then是一个函数,以x为this调用then函数, 且第一个参数是resolvePromise,第二个参数是rejectPromise
* 1. 当resolvePromise被以y为参数调用,执行[[Resolve]](promise,y)
* 2. 当rejectPromise被以r为参数调用,则以r为原因将promise拒绝
* 3. 控制其resolvePromise,rejectPromise只调用一次
* 4. 如果在调用then时抛出了异常
* 1. 如果resolvePromise或rejectPromise已经被调用,则忽略它
* 2. 否则,以e为reason将其promise拒绝
* 4. 如果then不是一个函数, 则以x为值fulfill promise
* @param {*} promise2
* @param {*} x
* @param {*} resolve
* @param {*} reject
* @returns
*/
function resolvePromise(promise2, x, resolve, reject) {
// 核心流程
if (promise2 === x) {
// 1. 如果promise和x的值指向同一个值, 使用TypeError作为原因将promise拒绝. 避免循环引用
return reject(new TypeError("error"));
}
//自己写的Promise要与别人的promise兼容 考虑不是自己写的promise情况
if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called = false;
try {
// 别人的promise可能调用成功后 还能调用失败, 取值时可能发生异常
//规范 2.3.3.1
let then = x.then;
if (typeof then === "function") {
then.call(
x, // 3. 以x为this 调用then
(y) => {
if (called) {
return;
}
called = true;
resolvePromise(promise2, y, resolve, reject); // 递归解析 直到不是promise为止
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
// 规范 2.3.3.4
resolve(x);
}
} catch (e) {
// 3-2. 如果在取x.then值时抛出了异常, 则以这个异常为原因将promise拒绝
if (called) return;
called = true;
reject(e);
}
} else {
// 4 如果不是一个函数, 则以x为值 fulfilled promise
// 规范 2.3.4,x 为基本类型
resolve(x);
}
}
then的值穿透
如果没有穿onFulfilled
或者onRejected
就默认设置v=>v
new Promise((resolve)=>{
resolve(1)
}).then().then().then().then(console.log)
// ...
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejected = typeof onRejected === "function" ? onRejected : (v) => {throw v};
// ...
catch
Promise.prototype.catch()
方法是.then(null, rejection)或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数
// ....
catch (errorFn){
return this.then(null,errorFn)
}
//....
finally
无论当前 Promise 是成功还是失败,调用finally
之后都会执行finally
中传入的函数,并且将值原封不动的往下传。
//....
finally(callback){
return this.then(
data=> Promise.resolve(callback()).then(()=> data),
error=> Promise.resolve(callback()).then(()=> {throw errror})
)
}
//...
Promise.resolve 方法
Promise.resolve
是一个静态方法, 它返回一个promise
的一个成功态。
//......
static resolve(value){
return new Promise((resolve,reject)=>{
resolve(value)
})
}
//....
//useage
Promise.resolve('success').then(console.log)
Promise.reject 方法
Promise.reject
也是一个静态方法, 它返回promise
的一个拒绝态。
//.....
static reject(reason){
return new Promise((resolve, reject)=>{
reject(reject)
})
}
//...
// useage
Promise.reject('error').catch(console.log)
Promise.all
Promise.all()
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例.
会等待所有的promise全部完成,返回一个新的promise。 当其中有一个promise失败,那么这个promise就失败了。
多个异步并发执行。
如果参数中有一个promise
失败,那么Promise.all
返回的promise
对象失败。
在任何情况下,Promise.all
返回的 promise
的完成状态的结果都是一个数组
const promises = Promise.all([p1,p2,p3])
Promise.all()
方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve
方法,将参数转为 Promise 实例,再进一步处理。且返回的每个成员都是 Promise 实例。
static all(promises){
return new Promise((resolve,reject)=>{
let result = [];
let times = 0;
function prcessPromise(index, value){
result[index] = value;
if(++times === promises.length) return resolve(result)
}
for(let i = 0; i< promise.length; i++){
let p = promises[i]
if(p && typeof p.then === 'function'){
p.then(
data=> processPromise(i, data),
reject // 当有一个失败时, 就直接调用reject
);
}else{
prcessPromise(i,p)
}
}
})
}
Promise.race
只要有一个 promise 执行完,直接 resolve 并停止执行
static race(promises){
return new Promise((resolve,reject)=>{
for(let i = 0; i< promises.length; i++){
let p = promise[i];
if(p && typeof p.then === 'function'){
p.then(resolve,reject)
}else{
resolve(p)
}
}
})
}
Promise.allsettled
等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。跟Promise.all
的区别时, Promise.allSettled
是包含数组中的promise成功的还是失败的,并一起返回。
接受的结果与入参时的promise实例一一对应,且结果的每一项都是一个对象,告诉你结果和值,对象内都有一个属性叫status
,用来明确知道对应的这个promise实例的状态(fulfilled
或rejected
),fulfilled
时,对象有value
属性,rejected
时有reason
属性,对应两种状态的返回值。
const resolved = Promise.resolve(100)
const rejected = Promise.reject(-100)
const allSettle = Promise.allSettled([resolved,rejected]);
allSettle.then(console.log)
//[
// { status: 'fulfilled', value: 100 },
// { status: 'rejected', reason: -100 }
//]
实现
static allSettled(promises) {
return new Promise((resolve, reject) => {
const result = [];
let times = 0;
function processPromise(index, value) {
result[index] = value;
if (++times === promises.length) return resolve(result);
}
for (let i = 0; i < promises.length; i++) {
const p = promises[i];
if (p && typeof p.then === "function") {
p.then(
(value) => processPromise(i, value),
(error) => processPromise(i, error)
);
} else {
processPromise(i, p);
}
}
});
}
promise/deferred
什么是promise/deferred 模式
promise/deferred 模式是,根据promise/A 或者它的增强修改版promise/A+ 规范 实现的promise异步操作的一种实现方式。
异步的广度使用使得回调,嵌套出现,但是一但出现深度的嵌套,就会让coding的体验变得相当不愉快,而且代码后期的维护也是相当吃力的。promise/deferred模式的出现,会在一定程度上缓解这个问题。接下来我会根据promise/a 规范来介绍promise/deferred模式。
实现
static deferred(){
const dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve= resolve;
dfd.reject = reject;
})
return dfd
}
//useage
const { log } = require("console");
const fs = require("fs");
function readFile(filePath) {
const dfd = Promise.defeered();
log(dfd);
fs.readFile(filePath, "utf8", function (err, data) {
if (err) return dfd.reject(err);
dfd.resolve(data);
});
return dfd.promise;
}
readFile("./a.js").then(console.log);
完整代码
const PEDDING = "PEDDING";
const REJECTED = "REJECTED";
const FULFILLED = "FULFILLED";
/**
* promise解析方法
* promise解析过程: 是一个以promise和一个值作为参数的抽象过程, 可以表示为[[Resolve]](promise,x)
* 1. 如果promise和x的值指向同一个值, 使用TypeError作为原因将promise拒绝
* 2. 如果x是一个promise 则采用其状态
* 1. 如果x是pendding状态,promise必须保持pendding走到x fulfilled或者rejected
* 2. 如果x是fulfilled状态,将x的值用于fulfilled promise
* 3. 如果x是rejected状态,将x的值用于reject promise
* 3. 如果x是一个对象或者一个函数
* 1. 将then赋值x.then
* 2. 如果在取x.then值时抛出了异常, 则以这个异常为原因将promise拒绝
* 3. 如果then是一个函数,以x为this调用then函数, 且第一个参数是resolvePromise,第二个参数是rejectPromise
* 1. 当resolvePromise被以y为参数调用,执行[[Resolve]](promise,y)
* 2. 当rejectPromise被以r为参数调用,则以r为原因将promise拒绝
* 3. 控制其resolvePromise,rejectPromise只调用一次
* 4. 如果在调用then时抛出了异常
* 1. 如果resolvePromise或rejectPromise已经被调用,则忽略它
* 2. 否则,以e为reason将其promise拒绝
* 4. 如果then不是一个函数, 则以x为值fulfill promise
* @param {*} promise2
* @param {*} x
* @param {*} resolve
* @param {*} reject
* @returns
*/
function resolvePromise(promise2, x, resolve, reject) {
// 核心流程
if (promise2 === x) {
// 1. 如果promise和x的值指向同一个值, 使用TypeError作为原因将promise拒绝
return reject(new TypeError("error"));
}
//自己写的Promise要与别人的promise兼容 考虑不是自己写的promise情况
if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called = false;
try {
// 别人的promise可能调用成功后 还能调用失败, 取值时可能发生异常
let then = x.then;
if (typeof then === "function") {
then.call(
x, // 3. 以x为this 调用then
(y) => {
if (called) {
return;
}
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
// 3-2. 如果在取x.then值时抛出了异常, 则以这个异常为原因将promise拒绝
if (called) return;
called = true;
reject(e);
}
} else {
// 4 如果不是一个函数, 则以x为值 fulfilled promise
resolve(x);
}
}
class Promise {
constructor(executor) {
this.value = undefined; // 成功的原因
this.status = PEDDING; // promise的状态
this.reason = undefined; // 失败的原因
this.onFulfilledCallbacks = []; // 存放成功的回调方法
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === PEDDING) {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
this.value = value;
this.status = FULFILLED;
// 6.1 当promise fulilled 后 所有onFulfilled 必须按照其注册顺序执行
this.onFulfilledCallbacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.status === PEDDING) {
this.reason = reason;
this.status = REJECTED;
// 6.2 当promise rejected后, 所有onRejected 必须按照其注册顺序执行
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
// 1. then方法接受两个参数
// 验证onFulfilled 和 onRejected 的类型
// 5 onRejected 和 onFulfilled 必须当做函数调用
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) => v;
onRejected = typeof onRejected === "function" ? onRejected : (v) => v;
// 实现链式调用
let promise2 = new Promise((resolve, reject) => {
// 订阅方法
if (this.status === FULFILLED) {
// 2 onFulfilled 必须在 promise fulilled之后调用。 且promise的value是其第一个参数
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// 7.1 此时x可能是一个promise, 如果是promise 需要看一下promise是成功还是失败。 .then, 如果成功则吧
// 成功的结果调用promise2的resolve传递进去, 失败则同理
// 总结 x的值 决定是调用promise2的resolve还是reject, 如果是promise,则取他的状态,如果是普通值
// 就直接调用resolve
resolvePromise(promise2, x, resolve, reject); // 解析promise流程
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
// 3 onRejected 必须 在reject之后调用 , 且promise的reason为它的第一个参数
// 失败调用失败的方法
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
// 4 onRejected 和 onFulfilled只允许在 execution context 栈 仅包含你平台代码时运行
if (this.status === PEDDING) {
// 6.1 把onFulfilled 缓存起来, 当resolve时 按照其添加顺序执行
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// 6.2 把onRejected 缓存起来 在调用reject时再按照其添加顺序执行
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
// 7. then 必须返回一个promise
return promise2;
// - .如果 onFulfilled 或者 onRejected 返回了值x , 则执行promise的解析流程。
// - .如果onFulfilled 或者 onRejected抛出异常,则promise2应当以e为reason被拒绝
// - .如果onFulfilled不是一个函数且promise1已经fulfilled,则promise2必须以promise1的值fulfilled
// - .如果onRejected不是一个函数 且promise1已经rejected, 则promise2必须以相同的reason被拒绝
}
catch(errorFn) {
return this.then(null, errorFn);
}
// 无论是成功还是失败 都会执行
// 可以返回一个promise
finally(cb) {
return this.then(
(data) => {
return Promise.resolve(cb()).then(() => data);
},
(err) => {
return Promise.resolve(cb()).then(() => {
throw err;
});
}
);
}
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
});
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
/**
* 等所有的promise全部完成
* 但当其中有一个失败了 那么这个promise就失败了
* 多个异步 并发请求
*/
static all(promises) {
return new Promise((resolve, reject) => {
let result = [];
let times = 0;
const processSucccess = (index, val) => {
// 会出现某些then结果速度快些 所以采用result[index]
result[index] = val;
if (++times === promises.length) {
resolve(result);
}
};
for (let i = 0; i < promises.length; i++) {
const p = promises[i];
if (p && typeof p.then === "function") {
p.then(
(data) => processSucccess(i, data),
// 如果有一个失败了 就执行失败
reject
);
} else {
processSucccess(i, p);
}
}
});
}
/**
* 其中一个完成了 但是剩下的还会继续执行
*/
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
const p = promises[i];
if (p && typeof p.then === "function") {
p.then(resolve, reject);
} else {
resolve(p);
}
}
});
}
static deferred() {
const dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
static allSettled(promises) {
return new Promise((resolve, reject) => {
const result = [];
let times = 0;
function processPromise(index, value) {
result[index] = value;
if (++times === promises.length) return resolve(result);
}
for (let i = 0; i < paromise.length; i++) {
const p = promises[i];
if (p && typeof p.then === "function") {
p.then(
(value) => processPromise(i, value),
(error) => process(i, error)
);
} else {
processPromise(i, p);
}
}
});
}
}