# Promise
# Promise 的作用
- 解决并发问题 (同步多个异步方法的执行结果)
- 链式调用问题 (先获取 name 再通过 name 获取 age 这种问题) 解决多个回调嵌套的问题
# Promise 简介
Promise
是一个类
- 每次
new
一个Promise
都需要传递一个执行器,执行器是立即执行的 - 执行器函数中有两个参数
resolve
reject
- 默认
Promise
有三个状态pending(等待)
=>resolve(成功)
reject(失败)
- 一旦成功不能失败,一旦失败不能成功
- 每个
promise
都有一个then
方法
promise
的链式调用
- 普通值表示不是
promise
也不是错误(then
回调中返回的)会走下一个then
的成功 - 如果返回的是一个
promise
那么这个promise
会执行,并且采用他的状态 - 抛出错误 走
then
的失败方法 - 返回一个新的
promise
来实现链式调用
# promise
基础用法实例
let p = new Promise((resolve, reject) => {
resolve("success");
throw new Error("失败"); //如果抛出异常也会执行成功
});
p.then(
(data) => {
console.log(data);
},
(err) => {
console.log(err);
}
);
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("resolve在then之后执行"); // 发布
}, 1e3);
});
// 订阅多个then方法
p2.then(
(data) => {
console.log(data);
},
(err) => {
console.log(err);
}
);
p2.then(
(data) => {
console.log(data);
},
(err) => {
console.log(err);
}
);
# promise
基础用法的实现
const PENDING = "PENGDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
console.log("---------------引入成功");
class Promise {
constructor(executor) {
this.value = undefined;
this.reason = undefined;
this.status = PENDING;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
this.onResolvedCallbacks.forEach(fn => fn()); // 发布 有可能resolve在then的后边执行,此时先将方法存放起来,状态改变为成功时依次执行这些方法(同一个示例订阅了多个then方法)
}
};
let reject = reason => {
if (this.status === PENDING) {
this.value = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
// 创建promise executor(执行器)会立即执行
// 这里可能会发生异常
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.value);
}
if (this.status === REJECTED) {
onRejected(this.reason);
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
// 外面在包一层函数 可以在这里再做一些其他的事 todo...
onFulfilled(this.value);
});
this.onRejectedCallbacks.push(() => {
// 外面在包一层函数 可以在这里再做一些其他的事 todo...
onRejected(this.reason);
});
}
}
}
// 导出当前类 commonjs定义的方式
module.exports = Promise;
# promise
链式调用用法实例
const fs = require("fs");
// 先看一看古老的用法
fs.readFile("name1.txt", "utf8", function(err, data) {
if (err) {
return console.error(err);
}
fs.readFile(data, "utf8", function(err, data) {
if (err) {
return console.error(err);
}
console.log(data);
});
});
/**
* desc promise的链式调用
* 1) 普通值表示不是promise 也不是错误(then回调中返回的)
* 2)如果返回的是一个promise 那么这个promise会执行,并且采用他的状态
*/
// function readFile(...args) {
// return new Promise((resolve, reject) => {
// fs.readFile(...args, function(err, data) {
// if (err) reject(err);
// resolve(data);
// });
// });
// }
// readFile("name1.txt", "utf8")
// .then(data => {
// return readFile(data, "utf8");
// })
// .then(
// data => {
// console.log(data);
// },
// err => {
// console.log(err);
// }
// );
const Promise = require("./promise的链式调用实现");
// 验证promise2 不能和 x是一个对象的例子
// let p = new Promise((resolve, reject) => {
// resolve("hello");
// });
// // promise2
// let promise2 = p.then(
// data => {
// return promise2; // x
// },
// err => {
// console.log(err);
// }
// );
// promise2.then(
// data => {
// console.log(data);
// },
// err => console.log(err)
// );
// 验证resolve的也是一个promise的情况 即源码中的y也是一个promise的情况
let p2 = new Promise((resolve, reject) => {
resolve(
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("嘿嘿嘿");
}, 1000);
})
);
}, 1000);
})
);
});
// promise2
let promise3 = p2
.then(
data => {
console.log(data);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("嘿嘿嘿");
}, 1000);
})
);
}, 1000);
});
},
err => {
console.log(err);
}
)
.then(
data => {
console.log("s:" + data);
},
err => console.log(err)
);
# promise
链式调用实现
const PENDING = "PENGDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
console.log("---------------引入成功");
// promise处理函数
const resolvePromise = (promise2, x, resolve, reject) => {
// 处理x的类型来决定是调用resolve还是reject
// 必须要写的很严谨
// promise2 和 x 不能是同一个对象 自己等待自己完成进入死循环 直接抛出错误
if (promise2 === x) {
return reject(
new TypeError(`Chaining cycle detected for promise #<Promise>`)
);
}
// 判断x是不是一个普通值 先认为他是一个promise
if ((typeof x === "object" && x !== null) || typeof x === "function") {
// typeof null === 'object'
let called; // 默认情况下没有成功或者失败
try {
let then = x.then; // 先判断x里面是不是有then 如果有错误就抛出错误
if (typeof then === "function") {
// 这里就确定是promise了
// x.then(()=>{},()=>{}) 这样会再次调用了一下x.then 会导致一些极端情况的问题
then.call(
x,
y => {
if (called) return; // 防止多次调用
called = true;
// y有可能还是一个promise 所以递归解析 直到可以解析为一个普通值了
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (called) return; // 防止多次调用
called = true;
reject(r);
}
);
} else {
// 这里就是普通值 是个对象 没有成功或者失败 所以不用改变called的值
resolve(x);
}
} catch (e) {
if (called) return; // 防止多次调用
called = true;
reject(e); // 就抛出错误
}
} else {
// 不是promise
resolve(x);
}
};
class Promise {
constructor(executor) {
this.value = undefined;
this.reason = undefined;
this.status = PENDING;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = value => {
// 如果new Promise里的resolve直接返回一个新的promise时 递归调用resolve直到返回一个普通值
if (value instanceof Promise) {
return value.then(resolve, reject);
}
// 只有是PENDING状态的时候才能改变状态
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
this.onResolvedCallbacks.forEach(fn => fn()); // 发布 有可能resolve在then的后边执行,此时先将方法存放起来,状态改变为成功时依次执行这些方法(同一个示例订阅了多个then方法)
}
};
let reject = reason => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
// 创建promise executor(执行器)会立即执行
// 这里可能会发生异常
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;
onRejected =
typeof onRejected === "function"
? onRejected
: err => {
throw err;
};
// then方法调用后应该返回一个新的promise
let promise2 = new Promise((resolve, reject) => {
// 应该在返回的promise中取到上一个promise的状态,来决定promise2走resolve还是reject
if (this.status === FULFILLED) {
// 当前的onFulfilled,onRejected不能在当前的上下文中执行,为了确保promise2的存在加上setTimeout改为异步
setTimeout(() => {
try {
let x = onFulfilled(this.value); // 当前/上一个 promise返回的值(可能是promise,可能是普通值,可能是个错误)
resolvePromise(promise2, x, resolve, reject); // 处理x的类型来决定是调用resolve还是reject
} catch (e) {
reject(e);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason); // 当前/上一个 promise返回的值(可能是promise,可能是普通值,可能是个错误)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
// 外面在包一层函数 可以在这里再做一些其他的事 todo...
setTimeout(() => {
try {
let x = onFulfilled(this.value); // 当前/上一个 promise返回的值(可能是promise,可能是普通值,可能是个错误)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
// 外面在包一层函数 可以在这里再做一些其他的事 todo...
setTimeout(() => {
try {
let x = onRejected(this.reason); // 当前/上一个 promise返回的值(可能是promise,可能是普通值,可能是个错误)
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return promise2;
}
// catch就是then的语法糖
catch(errCallback) {
return this.then(null, errCallback);
}
// 静态方法 可以直接被 Promise.resolve()这种方式调用
// 静态方法 是可以被类直接调用 不可以被示例调用,可以继承
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
});
}
// 静态方法 可以直接被 Promise.reject()这种方式调用
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
}
// 测试promise是否符合a+规范 全局安装 promises-aplus-tests包 执行 promises-aplus-tests 文件名
Promise.deferred = function() {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
// 导出当前类 commonjs定义的方式
module.exports = Promise;
# promise/A+
验证通过的源码
// 自己再重新写几遍 2遍
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
return reject(new TypeError(`自己等自己,等傻了吧#<promise>`));
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called;
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 (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
};
class Promise {
constructor(executor) {
this.value = undefined;
this.reason = undefined;
this.status = PENDING;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
let 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());
}
};
let reject = reason => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;
onRejected =
typeof onRejected === "function"
? onRejected
: err => {
throw err;
};
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.status === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return promise2;
}
catch(errCallback) {
return this.then(null, errCallback);
}
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
});
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
}
Promise.deferred = function() {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;
# promise.all
的实现
// promise.all 全部 处理多个异步的并发问题
let fs = require("fs").promises;
// 全部完成才算完成,如果有一个失败 就失败
// Promise.all 是按照顺序执行的
const isPromise = value => {
if (
(typeof value === "object" && value !== null) ||
typeof value === "function"
) {
return typeof value.then === "function";
}
return false;
};
// 开始写all方法
Promise.all = promises => {
return new Promise((resolve, reject) => {
let arr = [];
let i = 0;
let processData = (index, data) => {
arr[index] = data;
if (++i === promises.length) {
resolve(arr);
}
};
for (let i = 0; i < promises.length; i++) {
let current = promises[i];
if (isPromise(current)) {
current.then(data => {
processData(i, data);
}, reject);
} else {
processData(i, current);
}
}
});
};
Promise.all([
fs.readFile("./name.txt", "utf8"),
1,
2,
3,
fs.readFile("./age.txt", "utf8")
]).then(
data => {
console.log(data);
},
err => {
console.log(err);
}
);