Promise笔记

Promise笔记

promise的初衷是实现异步操作,支持链式回调,处理回调地狱;

实例对象属性

Promise的状态 [PromiseState]

pending 初始状态/未决定的

resolved/fulfilled 成功

rejected 失败

Promise 对象的值

保存对象【成功/失败】的结果

resolve 成功

reject 失败

Promise的方法

Promise.resolve;(value)=>{} value:成功的数据或promise对象

说明:返回一个成功/失败的promise对象

实例:

javascript 复制代码
let p1 = Promise.resolve(521);
    let p2 = new Promise((resolve, reject) => {
      resolve('success')
    })
    let p3 = Promise.resolve(new Promise((resolve, reject) => {
      resolve('ok')
    }))
    let p4 = Promise.resolve(new Promise((resolve, reject) => {
      reject('err');
    }))

    console.log(p1); //Promise {<fulfilled>: 521}
    console.log(p2); //Promise {<fulfilled>: 'success'}
    console.log(p3); //Promise {<fulfilled>: 'ok'}
    p4.catch(reason => {
      console.log(reason);//err
    })
Promise.reject;(reason)=>{} reason:失败的原因

说明:返回一个失败的promise对象,返回结果只能是一个失败的

实例:

javascript 复制代码
 let p1 = Promise.reject(521);
    // console.log(p1);//失败这样打印会报错
    p1.catch(reason => {
      console.log(reason);
    })
    let p2 = Promise.reject(new Promise((resolve, reject) => {
      reject('err');
    }))
    p2.catch(reason => {
      console.log(reason);
    })
Promise.all(常用);(promises)=>{} promises:包含n个promise的数组

说明:返回一个新的promise,只有所有的promise都成功才成功(返回PromiseState:fulfilled,PromiseResult:成功的结果),只要有一个失败就直接失败(返回PromiseState:rejected,PromiseResult:失败的结果)

实例:

javascript 复制代码
let p1 = Promise.resolve(521);
    let p2 = Promise.resolve('success');
    let p3 = Promise.resolve('成功');
    // let p4 = Promise.reject('err');

    let result = Promise.all([p1, p2, p3]);
    // let result = Promise.all([p1, p2, p4]);
    console.log(result);
    result.then(value => {
      console.log(value);
    }).catch(reason => {
      console.log(reason);
    })
Promise.rase(常用);(promises)=>{} promises:包含n个promise的数组

说明:返回一个新的promise对象,返回第一个完成promise的结果状态;如果所有 Promise 都拒绝,返回的 Promise 也将拒绝,拒绝的理由是一个聚合错误,包含所有 Promise 的拒绝理由。

实例:

javascript 复制代码
let p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(521)
      }, 1000)
    });
    let p2 = Promise.resolve('success');
    let p3 = Promise.resolve('成功');
    let p4 = Promise.reject('err');
    // let result = Promise.race([p1, p2, p3]);
    let result = Promise.race([p4, p2, p3]);
    console.log(result);
Promse.any;(promises)=>{} promises:包含n个promise的数组

说明:返回一个新的promise,返回第一个promise状态成功的结果,如果都没有成功则返回AggregateError类型的实例,它是Error的一个子类,用于把单一的错误集合 在一起;

实例:

javascript 复制代码
let p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(521)
      }, 1000)
    });
    let p2 = Promise.resolve('success');
    let p3 = Promise.resolve('成功');
    let p4 = Promise.reject('err');
    let p5 = Promise.reject('fail');
    let result = Promise.any([p4, p5])
    // let result = Promise.any([p4, p2, p1])
    console.log(result);

使用与封装

面试问题

1.promise的状态是否可以改变,如果可以是如何改变的?

答:promise的状态是可以由初始状态pending转为resolved/rejected的状态;但是resolved与rejected之间的状态不能相互转化;

转化的方法:(1)resolve(value):由初始状态转化为resolved;

(2)reject(reason):由初始状态转化为rejected;

(3)抛出异常:例如使用throw由初始状态转化为rejected;

2.一个promise置顶多个成功/失败回调函数,都会调用吗(对于promise的结果使用console.log()与alert()等方法进行多个调用,当状态发生变化时都会进行调用吗)

答:当promise发生改变时对应状态都会调用;

3.改变promise状态和指定回调函数谁先谁后?(改变promise的状态指的就是在new Promise中通过结果来改变其状态;指定回调就是通过then()/catcch()对实例的promise进行回调处理)

答:1.都有可能。在正常情况下是先指定回调在改变状态,但是也可能先改变状态,在执行回调(因为二者是异步进行的,无法判断他们的执行时间)

2.如何先改变状态在指定回调?

(1)在执行器中直接调用resolve()/reject();(2)延长更长时间才调用then(),(在then中使用定时器等方法

)

3.什么时候才能获得数据(对于promise实例完成后传出的数据)

(1)如果先置顶回调,那么当状态发生改变时,回调函数就会调用,得到数据;

(2)如果先改变状态,那么当执行回调时,回调函数就会调用,得到数据;

4.promise.then()返回的新的promise的结果状态又什么决定?(let result = p1.then()中result也是一个promise,其状态又什么决定)

**简单表达:**由then()指定的回调函数执行的结果来决定
详细描述:

1.如果promise中的内容是抛出异常,新的promise状态为rejected,使用reason将异常抛出(例如使用console.log()进行结果展示)

2.如果返回的是有个非promise的任意值,新promise状态将变为resolve,使用value展示结果;

3.如果返回的是另一个新的promise,此promise的结果将会是新的promise的结果;

javascript 复制代码
// 指定回调:通过p1.then()回调实例
    // 改变状态,promise状态从初始状态转化为其他状态
    let p1 = new Promise((resolve, reject) => {
      resolve('success');
    })
    let result = p1.then(value => {
      // 1.抛出错误
      // throw '出了问题';
      // 2.返回的是一个非promise的任意值
      // return 521;
      // 3.返回结果是Promise对象
      return new Promise((resolve, reject) => {
        // resolve('success');
        reject('err');
      }, reason => {
        console.warn(reason);
      })
    })
    console.log(result);
5.promise如何串联多个操作任务?

1.promise的then()返回一个新的promise,可以写成then()的链式调用;

2.通过then的链式调用串联多个同步/异步任务;

javascript 复制代码
 let p = new Promise((resolve, reject) => {
      resolve('OK');
    })

    p.then(value => {
      return new Promise((resolve, reject) => {
        resolve('success');
      })
    }).then(value => {
      console.log(value);//success
    }).then(value => {
      console.log(value);//undefined
    })
6.promise异常传透?

1.当使用promise的then的链式调用时,可以在最后指定失败的回调;

2.前面任何操作了异常,都会传到最后失败的回调中处理;(在catch()中显示前面的异常原因)

7.中断promise链?

说明:当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数;

办法:在回调函数中返回一个pendding状态的promise对象;

javascript 复制代码
 let p = new Promise((resolve, reject) => {
      resolve('success');
    })

    p.then(value => {
      console.log('111');
      // 中断链式的方法:返回一个初始状态的promise
      return new Promise(()=>{})
    }).then(value => {
      console.log('222');
    }).then(value => {
      console.log('333');
    }).catch(reason => {
      console.warn(reason);
    })

promise的常规使用

node读取文档内容
javascript 复制代码
const fs = require('fs');
// 原方法读取数据
// fs.readFile("./text/demo1.txt", (err, data) => {
//   if (err) throw err;
//   console.log(data.toString());
// })


// 使用promise读取数据
const p = new Promise((resolve, reject) => {
  fs.readFile("./text/demo1.txt", (err, data) => {
    if (err) reject(err);
    resolve(data.toString());
  })

})
p.then(res => {
  console.log(res);
}).catch(err => {
  console.log(err);
});

// 封装读取方法
const mineReadFile = function (url) {
  return new Promise((resolve, reject) => {
    fs.readFile(url, (err, data) => {
      if (err) reject(err)
      resolve(data.toString())
    })
  })
}

mineReadFile('./text/demo1.txt').then(value => {
  console.log(value);
}, reason => {
  console.log(reason);
})
使用promise调用ajax
javascript 复制代码
<button id="demo">点击请求</button>
  <script>
    // 原生使用
    let demo = document.querySelector("#demo")
    demo.addEventListener('click', () => {
      // 1.创建对象
      const xhr = new XMLHttpRequest();
      // 2.初始化
      xhr.open('GET', 'http://127.0.0.1/my/userList?page=1&pageSize=5&roleId=0');

      xhr.setRequestHeader('Authorization',
        'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiIiwibmFtZSI6IueuoeeQhuWRmCIsInBob25lIjoiNjY2NjYiLCJ1c2VyUGljIjoiaHR0cDovLzEyNy4wLjAuMTo4MC9zdGF0aWMvaW1hZ2UxNzAxNjMyMDA2ODg1LmpwZyIsInJvbGVJZCI6MSwidXNlcl9waWMiOiIiLCJpYXQiOjE3MjcyNzA0MjAsImV4cCI6MTcyNzM1NjgyMH0.SAC-qFKdM0-iLnGO-8wUIf0UE_ylqcSNch8EGOg7hAc'
        )
      // 3.发送
      xhr.send();
      // 4.处理响应结果
      // 通常处理方法
      // xhr.onreadystatechange = function () {
      //   if (xhr.readyState === 4 && xhr.status === 200) {
      //     console.log(xhr.response);
      //   }
      // }

      xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
          if (xhr.status >= 200 && xhr.status < 300) {
            console.log(xhr.response);
          } else {
            console.log(xhr.status);

          }
        }
      }

    })

    // 使用promise
    demo.addEventListener('click', () => {
      // 1.创建对象
      const p = new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        // 2.初始化
        xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts');
        // 3.发送
        xhr.send();
        // 4.处理响应结果
        // 通常处理方法
        // xhr.onreadystatechange = function () {
        //   if (xhr.readyState === 4 && xhr.status === 200) {
        //     console.log(xhr.response);
        //   }
        // }

        xhr.onreadystatechange = function () {
          if (xhr.readyState == 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
              resolve(xhr.response)
            } else {
              reject(xhr.status)

            }
          }
        }
      })
      p.then(value => {
        console.log(value);
      }, reason => {
        console.log(reason);
      })
    })

    // promise封装方法
    const mineSendAjax = url => {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.send();
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
              resolve(xhr.response);
            } else {
              reject(xhr.status);
            }
          }
        }
      })

    }
    demo.addEventListener('click', () => {
      mineSendAjax('https://jsonplaceholder.typicode.com/posts').then(value => {
        console.log(value);
      }, reason => {
        console.log(reason);
      })
    })
  </script>
相关推荐
brief of gali6 分钟前
记录一个奇怪的前端布局现象
前端
-一杯为品-36 分钟前
【51单片机】程序实验5&6.独立按键-矩阵按键
c语言·笔记·学习·51单片机·硬件工程
前端拾光者1 小时前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
Json_181790144801 小时前
电商拍立淘按图搜索API接口系列,文档说明参考
前端·数据库
风尚云网1 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
木子02041 小时前
前端VUE项目启动方式
前端·javascript·vue.js
GISer_Jing2 小时前
React核心功能详解(一)
前端·react.js·前端框架
捂月2 小时前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
深度混淆2 小时前
实用功能,觊觎(Edge)浏览器的内置截(长)图功能
前端·edge
Smartdaili China2 小时前
如何在 Microsoft Edge 中设置代理: 快速而简单的方法
前端·爬虫·安全·microsoft·edge·社交·动态住宅代理