1178 字
3 分钟
Promise 学习笔记
2022-05-05

Promise 学习笔记#

一、Promise 简介#

​ Promise 是 JS 中进行异步编程的新解决方案。(旧方案是单纯使用回调函数)

​ 优点:

  • 指定回调函数更加灵活
  • 支持链式调用,可以解决毁回调地狱问题

二、Promise 初体验#

​ resolve、reject 两者都是函数类型的数据,分别为成功和失败后的回调。

​ 在内部封装时可以携带参数。

const p = new Promise((resolve, reject) => {
setTimeout(() => {
if (xxx) {
resolve(arg1); //将 promise 对象的状态设置为成功
}
else {
reject(arg2); //将 promise 对象的状态设置为失败
}
}, 1000)
})
// 第一个为成功回调,第二个为失败回调
p.then((arg) => {
alert('success, the arg is ' + arg);
}, (arg) => {
alert('failed' + arg);
})

​ 实际使用中也可以这样封装:

function asyncTask(arg) {
return new Promise((resolve, reject) => {
if (xxx) {
resolve();
}
else {
reject();
}
})
}
const obj = asyncTask(xxx);
obj.then((arg1) => {
...
}, (arg2) => {
...
})

util.promisify 方法:

// 可以借助 node.js 的该方法来将函数转化为 promise 风格
const util = require('util');
const fs = require('fs');
let mineReadFile = util.promisify(fs.readFile);
mineReadFile(...).then(...);

三、Promise 状态与值#

​ 指实例对象中的一个属性:PromiseState

​ 只有以下两种转变情况:

pending -> fulfilled

pending ->rejected

​ 且一个 promise 对象只能改变一次状态。无论变为成功还是失败,都会有一个结果数据。成功的结果数据一般称为 value,失败的结果数据一般称为 reason。

​ Promise 对象的值:

​ 实例对象中的另一个属性 PromiseResult,保存着对象成功/失败的结果


四、Promise 的基本流程#

image-20220418213510140


五、Promise API#

1、构造函数#

executor = (resolve, reject) => {};
Promise(excutor) {};

​ 注:executor 函数会在 Promise 内部立即同步调用,异步操作在执行器中执行。

2、Promise.prototype.then()#

Promise.prototype.then(onResolved,onRejected) => {};
  • onResolved 函数:成功的回调函数
  • onRejected 函数:失败的回调函数

​ 注:指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调,返回一个新的 promise 对象

3、Promise.prototype.catch()#

Promise.prototype.catch(reason => {});

​ 只用于指定失败的回调。

4、Promise.resolve()#

var obj = Promise.resolve(arg);

​ 如果传入的是非 Promise 对象,则返回结果为成功 Promise 对象。

​ 如果传入的是 Promise 对象,参数的结果决定了 resolve 的结果。

​ 如下方返回一个成功 Promise 对象:

let p1 = Promise.resolve(new Promise((resolve, reject) => {
// resolve('It\' OK.');
reject('Error');
}))
console.log(p1);
// catch
p1.catch(reason => {
console.log(reason);
})

5、Promise.reject()#

var obj = Promise.reject(arg);

​ 传入任何类型值,返回都为失败 Promise 对象,而失败的结果是传递的值或对象

​ 如下方返回一个失败 Promise 对象

let p2 = Promise.resolve(new Promise((resolve, reject) => {
resolve('It\' OK.');
}))
console.log(p2);

6、Promise.all()#

Promise.all((promises) => {})

​ 说明:返回一个新的 promise,只有所有的 promise 都成功才成功,只要有一个失败了就直接失败。

​ 成功返回结果是所有 promise 对象返回结果的数组,

​ 失败返回结果是失败 promise 对象的返回结果。

7、Promise.race()#

Promise.race((promises) => {})

​ 说明:返回一个新的 promise,第一个完成(改变状态)的 promise 的结果状态就是最终的结果状态。


六、Promise 关键问题#

1、Promise 状态改变的方法#

  • resolve(value):如果当前是 pending 就会变为 resolved
  • reject(reason):如果当前是 pending 就会变为 rejected
  • 抛出异常:如果当前是 pending 就会变为 rejected
let p = new Promsie((resolve, reject) => {
// resolve
resolve('OK');
// reject
reject('error');
// throw exception
throw "Exception!";
})

2、指定多个成功/失败回调#

​ 一个 Promise 指定多个成功/失败回调,当promise改变为对应状态时都会调用

let p = new Promise((resolve, reject) => {
resolve('OK');
})
p.then(value => {
console.log(value+'!');
})
p.then(value => {
console.log(value+'!!');
})

3、改变状态与指定回调谁先谁后#

​ 都有可能。但一般执行器内是异步任务,因此一般是先指定回调。

​ 若要先改变状态:

  • 执行器内直接改变状态
  • 延迟更长时间再调用 then()

​ 得到数据的时间:

  • 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据。
  • 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据。

4、then() 方法返回结果#

​ 主要有三种情况:

let res = p.then(value => {
// 1. throw exception,那么失败,结果是异常
throw 'An exception!';
// 2. 返回结果是非 Promise 对象,那么成功,结果是该值
return 521;
// 3. 返回结果是 Promise 对象,那么成功和返回值都由该对象决定
return new Promise((resolve, reject) => {
// resolve('OK');
reject('error');
})
})

5、Promise 串联任务#

​ 比如串联两个异步任务与一个同步任务:

let p = new Promise((resolve, reject) => {
// 第一个异步 Promise
setTimeout(() => {
resolve('First OK');
}, 1000);
}).then(value => {
// 成功后告知第一个异步 Promise 完成,输出 'First OK'
console.log(value);
// 回调第二个异步 Promise
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Second OK');
}, 2000);
})
}).then(value => {
// 成功后告知第二个异步 Promise 完成,输出 'Second OK'
console.log(value);
// 该回调返回成功 Promise
}).then(value => {
// 第三个 Promise 回调开始,输出 undefined
console.log(value);
})

6、Promise 异常穿透#

​ Promise 链中任意层的失败可以穿透至最后层,而被捕获的现象。

​ 如:

// 中间任意层可以不指定失败捕获
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
}).then(value => {
throw 'Second layer exception!';
}).then(value => {
console.log(3);
}).then(value => {
console.log(4);
}).catch(reason => {
console.err(reason);
})

7、中断 Promise 链#

​ 有且只有一个方法:返回一个 pending 状态的 Promise 对象。

...
.then(value => {
...
return new Promise(() => {});
})
...

七、async 与 await#

1、async 函数#

​ async 函数的返回值为 Promise 对象,且其结果同样由函数执行的返回值决定。


2、await 表达式#

  • await 右侧的表达式一般为 promise 对象,但也可以是其它的值
  • 如果表达式是 promise 对象,await 返回的是 promise 成功的值
  • 如果表达式是其它值,直接将此值作为 await 的返回值

​ 注:

  • await 必须写在 async 函数中,但 async 函数中可以没有 await
  • 如果 await 的 Promise 失败了,就会抛出异常,需要捕获

3、结合使用的例子#

​ 异步依次读取文件:

const fs = require('fs');
const util = require('util');
const mineReadFile = util.promisify(fs.readFile)
!async function main() {
try {
let data1 = await mineReadFile('./1.txt');
let data2 = await mineReadFile('./2.txt');
let data3 = await mineReadFile('./3.txt');
console.log(data1 + data2 + data3);
}
catch(e) {
console.warn(e);
}
}();
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Promise 学习笔记
https://miku.top/posts/promise-learn/
作者
律回
发布于
2022-05-05
许可协议
CC BY-SA 4.0

部分信息可能已经过时

目录