前言
1.照猫画虎
- 1.
Promise是类 无需考虑兼容性
- 2.当
new Promise的时候 会传入一个执行器executor 此执行器是立即执行
- 3.当前
executor 给了两个函数参数(resolve, reject) 描述当前promise的状态
- 4.
promise中有三个状态 等待 成功 失败
- 默认为等待
- 如果调用
resolve 会走到成功
- 如果调用
reject 或者发生异常 会走失败
- 5.每个
promise实例都有一个then方法
- 6.
promise 一旦状态变化后不能更改
let Promise = require('./promise.js')
let promise = new Promise((resolve, reject) => {
resolve('ok')
})
promise.then((value)=>{
console.log("🚀 ~ success1", value)
}, (reason)=>{
console.log("🚀 ~ error1", reason)
})
promise.then((value)=>{
console.log("🚀 ~ success2", value)
}, (reason)=>{
console.log("🚀 ~ error2", reason)
})
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
const resolve = (value) => {
if (this.status === PENDING) {
this.value = value
this.status = FULFILLED
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECTED
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
if (this.status === REJECTED) {
onRejected(this.reason)
}
}
}
module.exports = Promise
2.异步处理
- 发布订阅模式
- 解决异步如何处理
- 假如有
setTimeout时, 当前上下文执行完 才会执行resolve()
let promise = new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('ok')
}, 3000)
})
promise.then((value)=>{
console.log("🚀 ~ success1", value)
}, (reason)=>{
console.log("🚀 ~ error1", reason)
})
promise.then((value)=>{
console.log("🚀 ~ success2", value)
}, (reason)=>{
console.log("🚀 ~ error2", reason)
})
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === PENDING) {
this.value = value
this.status = FULFILLED
this.onFulfilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECTED
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
if (this.status === REJECTED) {
onRejected(this.reason)
}
}
}
module.exports = Promise
3.链式调用(核心)
- 1.调用
then 会返回一个新的promise
- 2.
then中方法 返回是一个普通值, 会作为下一次 then 的成功结果
- 3.
then中方法 执行出错, 会作为下一次 then 的失败结果
- 4.
then中方法 返回的是一个promise对象 会根据promise的resolve, reject来处理 是走成功还是失败
- 5.无论
then走是成功还是失败 只要返回的是普通值 都会执行下一次then的成功
let Promise = require('./promise.js')
let promise = new Promise((resolve, reject)=>{ resolve('链式回调') })
let promise2 = promise.then(
value => { return value + '1' },
error => { return error + '1' }
);
promise2.then().then(null).then(
value => { console.log("🚀 ~ success", value) },
error => { console.log('🚀 ~ failure', error) }
);
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (value instanceof Promise) {
return value.then(resolve, reject)
}
if (this.status === PENDING) {
this.value = value
this.status = FULFILLED
this.onFulfilledCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECTED
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error }
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
}
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise2
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) { return reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise> 死循环')) }
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let called = false;
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject)
}, r => {
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x)
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
module.exports = Promise
promise规范测试
- 安装
npm install promises-aplus-tests -g
- 执行
promises-aplus-tests promise.js
- 如果测试没有错误 说明
promise写的符合规范
- 只针对
promise里的resolve, reject
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve= resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise
其他方法
Promise.resolve, Promise.reject, catch
class Promise {
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value)
})
}
static reject(value){
return new Promise((resolve,reject)=>{
reject(value);
})
}
catch(errorFn){
return this.then(null,errorFn)
}
}
race
- 采用最快的
Promise.race
- 其实数组中的每个promise都已执行
- 一方执行完 就立即停止
- 主要的最快的已经修改了
this.status状态
- 其他的也执行 但是
if判断 跳过
class Promise {
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)
}
}
})
}
}
let Promise = require('./promise.js')
let p1 = new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('成功')
}, 1000);
})
let p2 = new Promise((resolve,reject)=>{
setTimeout(() => {
reject('失败')
}, 500);
})
Promise.race([p1, p2]).then(
v => console.log(v),
e => console.log(e)
)
Promise.race([p1, p2, 1]).then(
v => console.log(v),
e => console.log(e)
)
let p3 = new Promise((resolve) => {
setTimeout(()=>{
resolve('p3成功')
}, 3000)
})
function warp(proParams) {
let abort;
let p = new Promise((resolve, reject) => {
abort = reject
})
let result = Promise.race([p, proParams])
result.abort = abort
return result
}
let p3IsTimeOut = warp(p3)
p3IsTimeOut.then(
value => console.log(value),
error => console.log(error)
)
setTimeout(() => {
p3IsTimeOut.abort('已超时一秒')
}, 1000)
finally
- 无论失败 还是成功 都会执行
- 并且可以继续
.then
- 成功时
cb() 返回的值 不会 往下传递 还是.then的value
- 失败时 执行完
cb() 并抛出错误(错误是会继续往下抛)
- 为什么使用
Promise.resolve?
- 因为
cb() 执行完 如果返回的值 Promise对象
- 直接执行
val.then(resovle, reject), 并返回新的promise
class Promise {
finally(cb) {
return this.then(
value => {
return Promise.resolve(cb()).then(() => value)
},
error => {
return Promise.resolve(cb()).then(() => { throw error })
}
)
}
}
let Promise = require('./source/promise3.js')
let p1 = new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('resolve: 成功')
}, 3000);
})
let p2 = p1.finally(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('123456');
}, 1000);
})
})
p2.then(value =>{
console.log(value)
}).catch(error => {
console.log("🚀 ~ catch", error)
})
node 中的promisify
// a.txt
这是个测试文件
const fs = require('fs')
function promisify(fn) {
return function(...args){
return new Promise((resolve, reject) => {
fn(...args, (err, data) => {
if(err) return reject(err);
resolve(data);
})
})
}
}
let p = promisify(fs.readFile)
p('./a.txt', 'utf8').then(v => console.log(v))
完