promise运行流程
promise:
graph TD
启动异步任务 --> 返回promise对象 --> 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)
fs读取文件封装和util.promisify(original)
fs读取文件封装
function myReadFile(path) {
return new Promise((resolve, reject) => {
require("fs").readFile(path, (err, data) => {
if (err) return reject(err);
resolve(data);
});
});
}
myReadFile("./文本文件.txt").then(
value=> {
console.log(value.toString());
},
reason=> {
console.log(reason);
}
);
util.promisify(original) 传入一个遵循常用的错误优先的回调风格的函数(即以(err,value)=>..回调作为最后一个参数),并返回一个返回promise的版本
- 参数original是一个Function
- 返回也是一个Function
const util = require("util");
const fs = require("fs");
let mineReadFile = util.promisify(fs.readFile);
mineReadFile("./文本文件.txt").then(
(value) => {
console.log(value.toString());
},
(reason) => {
console.log(reason);
}
);
promise的状态改变
- pending变为resolved
- pending变为rejected
- 只有这两种,且promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据。成功的结果数据一般称value,失败的结果数据一般称为reason
Promise的状态
实例对象的一个属性 [PromiseState]
- pending 未决定的
- resolved/fullfilled 成功
- rejected 失败
Promise 对象的值 实例对象中的另一个属性 [PromiseResult] 保存着异步任务 [成功/失败] 的结果
- resolve
- reject
API
Promise构造函数:Promise(excutor){}
- executor 函数:执行器 (resolve,reject)=>{}
- resolve 函数:内部定义成功时我们调用的函数 value=>{}
- reject 函数:内部定义失败时我们调用的函数 reason=>{}
- 说明:executor会在Promise内部立即同步调用,异步操作在执行器中执行
Promise.prototype.then方法:(onResolved,onRejected)=>{}
- onResolved 函数:成功的回调 (value)=>{}
- onReject 函数:失败的回调函数 (reason)=>{}
- 说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调返回一个新的promise对象
Promise.prototype.catch 方法:(onRejected)=>{}
- onRejected函数:失败的回调函数(reason)=>{}
Promise.resolve()
- 如果传入的参数为 非Promise类型的对象,则返回的结果为成功promise对象
- 如果传入的参数为Promise对象,则参数的结果决定了resolve的结果
let p1 = Promise.resolve(123)
console.log(p1);
let p = Promise.resolve(new Promise((resolve,reject)=>{
resolve('ok')
// reject('err')
}))
console.log(p);
Promise.reject()
let p = Promise.reject(new Promise((resolve, reject) => {
console.log('OK');
}))
console.log(p);
Promise.all(promises)
- promises:包含n个promise数组
- 说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败
let p1 = new Promise((resolve, reject) => {
resolve('OK')
})
let p2 = Promise.resolve('Success')
let p3 = Promise.resolve('Yes')
console.log(Promise.all([p1, p2, p3]));
Promise.race()
- promises:包含n个promise数组
- 说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK')
}, 1000)
})
let p2 = Promise.resolve('Success')
let p3 = Promise.resolve('Yes')
console.log(Promise.race([p1, p2, p3]));
Promise关键问题
如何改变promise的状态
- resolve(value):如果当前是pending就会变为resolved
- reject(reason):如果当前是pending就会变为rejected
- 抛出异常:如果当前是pending就会变成rejcted
一个promise指定多个成功/失败回调函数,都会调用吗? 当promise改变为对应状态时都会调用
改变promise状态和指定回调函数谁先谁后?
- 都有可能,正常情况下是先指定回调再改变状态,但是也可以先改状态再指定回调
- 如果先该状态再指定回调?
- 在执行器中直接调用resolve()/reject()
- 延迟更长时间才调用then()
- 什么时候才能得到数据
- 如果先指定回调,那当状态发生改变时,回调函数就会调用,得到数据
- 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
promise.then()返回的新promise的结果状态由什么决定?
- 简单表达:由then()指定的回调函数执行结果决定
- 详细表达:
- 如果抛出异常,新的promise变为rejected,reason为抛出异常
- 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
- 如果返回的是另一个新promise,此promise的结果就会成为新promise的结果
promise如果串连多个操作任务?
- promise的then()返回一个新的promise,可以开成then()的链式调用
- 通过then的链式调用串连多个同步/异步任务
promise异常传透?
- 当使用promise的then链式调用时,可以在最后指定失败的回调
- 前面任何操作出现了异常,都会传到最后失败的回调中处理
中断promise链?
- 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
- 办法:在回调函数中返回一个pendding状态的promise对象
自定义promise
class Promise {
constructor(executor) {
//声明属性
this.PromiseState = "pendding";
this.PromiseResult = null;
//保存then的回调
this.callback = [];
const self = this;
function resolve(data) {
if (self.PromiseState !== "pendding") return;
//改变状态
self.PromiseState = "fullfilled";
//改变结果
self.PromiseResult = data;
setTimeout(() => {
self.callbacks.forEach((item) => {
item.onResovled(data);
});
});
}
function reject(data) {
if (self.PromiseState !== "pendding") return;
self.PromiseState = "rejected";
self.PromiseResult = data;
setTimeout(() => {
self.callbacks.forEach((item) => {
item.onRejected(data);
});
});
}
try {
//实现同步调用
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onResovled, onRejected) {
// const self = this;
if (typeof onRejected !== Function) {
onRejected = (result) => {
throw result;
};
}
if (typeof onResovled !== Function) {
onRejected = (value) => value;
}
function callback(type) {
try {
let result = type(this.PromiseResult);
if (result instanceof Promise) {
result.then(
(v) => {
resolve(v);
},
(r) => {
reject(r);
}
);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
}
return new Promise((resolve, reject) => {
if (this.PromiseState === "fullfilled") {
setTimeout(() => {
callback(onResovled);
});
}
if (this.PromiseState === "rejected") {
setTimeout(() => {
callback(onRejected);
});
}
if (this.PromiseState === "pendding") {
this.callbacks.push({
onResovled: function () {
callback(onResovled);
},
onRejected: function () {
callback(onRejected);
},
});
}
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
static resolve(value) {
return new Promise((resolve, reject) => {
if (result instanceof Promise) {
return result.then(
(v) => {
resolve(v);
},
(r) => {
reject(r);
}
);
} else {
resolve(value);
}
});
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
static all(promises) {
return new Promise((resolve, reject) => {
let count = 0;
let arr = [];
for (const i = 0; i < promises.length; i++) {
promises[i].then(
(v) => {
count++;
arr[i] = v;
if (count === promises.length) {
resolve(arr);
}
},
(r) => {
reject(r);
}
);
}
});
}
static race(promises) {
return new Promise((resolve, reject) => {
for (const i = 0; i < promises.length; i++) {
promises[i].then(
(v) => {
resolve(v);
},
(r) => {
reject(r);
}
);
}
});
}
}
async 函数
- 函数的返回值为promise对象
- promise对象的结果由async函数执行的返回值决定
await表达式
- await右侧的表达式一般为promise对象,但也可以是其他的值
- 如果表达式是promise对象,await返回的是promise成功的值
- 如果表达式是其他值,直接将此值作为await的返回值
注意:
- await必须写在async函数中,但async函数中可以没有await
- 如果await的promise失败了,就会抛出异常,需要通过try...catch捕获处理