Promise 的主要使用

前言

回调 一直是JavaScript编程中比较令人纠结的写法,主要场景是用于处理 “并列”或者“并行”的操作,然后在回调函数中处理操作结果。这样子原生的回调写法就会带来一下的不便。

  • 回调结果状态不便管理
  • 回调方式自由松散,没有规范约束

例如下面的回调的写法

  1. function func(num, callback) {
  2. setTimeout(() => {
  3. try {
  4. let result = 1/num;
  5. callback(result, null);
  6. } catch(err) {
  7. callback(null, err);
  8. }
  9. }, 10)
  10. }
  11. func(1, (result, err) => {
  12. if( err ) {
  13. console.log(err)
  14. } else {
  15. console.log(result)
  16. }
  17. })

上述代码中,发现如果要处理回调结果 result和错误err ,后续的所有就必须在回调函数里面处理,而且回调函数里面还需要自己处理异常判断。 那如果是使用了Promise来处理回调操作,就可以用以下写法处理。

  1. function func(num, callback) {
  2. return new Promise((resolve) => {
  3. setTimeout(() => {
  4. let result = 1/num;
  5. resolve(result);
  6. }, 1000)
  7. })
  8. }
  9. func(1).then((result) => {
  10. console.log(result)
  11. }).catch((err) => {
  12. console.log(err)
  13. })

Promise能力

Promise 带来的能力是任务管理,常用的方式有

new Promise(...).then(onResolved, onRejected)

  • 任务状态管理
    • resolve 成功状态,对应 Promise.resolve
    • reject 失败状态,对应 Promise.reject
    • error 异常状态, 对应 Promise.rejectnew Promise().catch(onRejected)
  • Thenabled机制提供任务方法链
    • new Promise().then().then().catch()

resolve

处理任务的成功状态

  • 普通方式
  1. let p = new Promise((resolve) => {
  2. setTimeout(() => {
  3. let result = 1;
  4. resolve(result);
  5. }, 1000)
  6. })
  7. p.then((result)=>{ console.log(result) })
  • 快捷方式
  1. let p = Promise.resolve(1)
  2. p.then((result)=>{ console.log(result) })

reject

处理任务的失败状态

  • 普通方式
  1. let p = new Promise((resolve, reject) => {
  2. setTimeout(() => {
  3. let result = 2;
  4. reject(result);
  5. }, 100)
  6. })
  7. // 有两种方式获取失败状态
  8. // 第一种,通过then 第二个函数参数处理失败状态
  9. p.then((result)=>{
  10. console.log('success:',result);
  11. }, (result)=>{
  12. console.log('fail:',result);
  13. })
  14. // "fail: 2"
  15. // 第二种,或者通过,catch 获取失败状态
  16. p.then((result)=>{
  17. console.log('success:',result);
  18. }).catch((result)=>{
  19. console.log('error:',result);
  20. })
  21. // "error: 2"
  22. // 注意:如果两种方式同时使用的话
  23. // 只会被第一种方式reject操作失败的结果
  24. p.then((result)=>{
  25. console.log('success:',result);
  26. }, (result)=>{
  27. console.log('fail:',result);
  28. }).catch((result)=>{
  29. console.log('error:',result);
  30. })
  31. // "fail: 2"
  • 快捷方式
  1. let p = Promise.reject(2)
  2. p.then(null, result => console.log('fail:', result))
  3. // 或
  4. p.then().catch( result => console.log('error:', result))

catch

从上述 reject 的使用过程中,会发现, catch操作在没有设置 onRejected 处理的时候,会被catch 捕获失败处理。同时catch 也会捕获 onResolved 和 onRejected中出现的错误。

  • 正常情况下直接捕获reject结果
  1. let p = new Promise((resolve, reject) => {
  2. reject(3)
  3. });
  4. p.then((result) => {
  5. console.log('success:', result)
  6. }).catch((result) => {
  7. console.log('error:', result)
  8. })
  9. // "error: 3"
  • 捕获 onResolved 中错误异常
  1. let p = new Promise((resolve) => {
  2. resolve(3)
  3. });
  4. p.then((result) => {
  5. throw new Error('custom resolve error!')
  6. console.log('success:', result)
  7. }).catch((err) => {
  8. console.log('Custom error:', err)
  9. })
  10. // "Custom error: Error: custom resolve error!"
  • 捕获 onRejected 中错误异常
  1. let p = new Promise((resolve) => {
  2. reject(3)
  3. });
  4. p.then(null, (result) => {
  5. throw new Error('custom reject error!')
  6. console.log('fail:', result)
  7. }).catch((err) => {
  8. console.log('Custom error:', err)
  9. })
  10. // "Custom error: Error: custom reject error!"

后记

由于本书主要介绍 Koa.js的原理,主要涉及到Promiseresolverejectcatch 更多 关于 Promise 的原理和使用,请查看一下文档:

https://docs.microsoft.com/zh-cn/scripting/javascript/reference/promise-object-javascript