Promise学习笔记(一)

个人博客:Promise学习笔记(一)

一直有在用Promise,但是没有系统学过Promise,自然也不知道原理。现在就来学习一波。

1. 介绍

Promise是JS中进行异步编程的新解决方案。在这之前使用过回调函数进行异步编程。

Promise是一个构造函数,Promise对象用来封装一个异步操作并可以获取其成功或失败的结果值

Promise优点

  1. 支持链式调用,可解决回调地狱问题

回调地狱:回调函数嵌套使用

回调地狱导致的问题

  • 阅读困难(后期维护麻烦)

  • 不便于异常处理

  1. 指定回调函数的方式更灵活

    • Promise:启动异步任务 => 返回Promise对象 => Promise对象绑定回调函数
    • 纯用回调函数:必须在启动异步任务前指定

2. Promise 体验

2.1 抽奖

先来一个抽奖示例(隔1s后出结果)

2.1.1 回调函数版本

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Promise初体验</title></head><body><button class="btn" id="btn">抽奖</button><script>function rand() {return Math.floor(Math.random() * 100 + 1) // 返回1到100之前的随机数}const btn = document.querySelector("#btn")btn.addEventListener("click", function () {setTimeout(() => {let n = rand()if (n <= 50) {alert("恭喜你中奖了")} else {alert("很遗憾,你没有中奖")}}, 1000)})</script></body>
</html>

2.1.2 Promise版本

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Promise初体验</title>
</head><body><button class="btn" id="btn">抽奖</button><script>function rand() {return Math.floor(Math.random() * 100 + 1) // 返回1到100之前的随机数}const btn = document.querySelector("#btn")btn.addEventListener("click", function () {const p = new Promise((resolve, reject) => {// resolve 成功后执行的函数// reject 失败后执行的函数let n = rand()setTimeout(() => {if (n <= 50) {resolve(n) // 可以将Promise的状态设置为成功} else {reject(n) // 可以将Promise的状态设置为失败}}, 1000)})p.then(// 通过then方法指定成功或失败时的回调函数,第一个参数是成功时的回调,第二个参数是失败时的回调(value) => {alert(`恭喜你,中奖了,中奖号码是${value}`)},(value) => {alert(`真遗憾,你没有中奖,中奖号码是${value}`)})})</script>
</body></html>

2.2 文件读取

2.2.1 回调函数版本

const fs = require('fs')fs.readFile('./resource/content.txt', (err, data) => {if (err) {throw err}console.log(data.toString())
})

2.2.2 Promise版本

const fs = require('fs')let p = new Promise((resolve, reject) => {fs.readFile('./resource/content1.txt', (err, data) => {if (err) {reject(err)} else {resolve(data)}})
})p.then((value) => {console.log(value.toString())
}, (reason) => {console.log(reason)
})

2.3 AJAX

2.3.1 原生版本(回调函数)

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise封装AJAX</title>
</head><body><script>(function () {// 1. 创建对象const xhr = new XMLHttpRequest()// 2. 初始化xhr.open('GET', 'https://qcgx2i.api.cloudendpoint.cn/hello')   // 接口可能会无效,换一个有效的就行// 3. 发送xhr.send()// 4. 处理响应结果xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {console.log(xhr.response)} else {console.log(xhr.status)}}}})()</script>
</body></html>

2.3.2 Promise版本

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise封装AJAX</title>
</head><body><script>(function () {const p = new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open('GET', 'https://qcgx2i.api.cloudendpoint.cn/hello');xhr.send();xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {resolve(xhr.response) // 成功} else {reject(xhr.status)}}};})p.then((data) => {console.log(data)}, (statusCode) => {console.warn(statusCode)})})()</script>
</body></html>

3. 转化为Promise风格(promisify)

util.promisify():传入一个遵循常见的错误优先的回调风格的函数(即以(err, value) => {...}作为最后一个参数),并返回Promise版本。

const fs = require('fs')
const { promisify } = require('util')let pReadfile = promisify(fs.readFile)  // 把callback形式的异步api转化成promise形式的pReadfile('./resource/content.txt').then(value => {console.log(value.toString())})

4. Promise属性

4.1 Promise状态

实例对象中的一个属性[[PromiseState]],有三个值

  • pending:未决定
  • resolved(fulfilled):成功
  • rejected:失败

Promise的状态改变只有两种可能,且只能改变一次

  • pending变为resolved
  • pending变为rejected

成功的结果数据一般称为value,失败的结果一般称为reason

4.2. Promise对象的值

实例对象中的一个属性[[PromiseResult]],保存着异步任务成功或失败的结果

只能通过resolve()reject()PromiseResult进行修改

const fs = require('fs')let p = new Promise((resolve, reject) => {fs.readFile('./resource/content1.txt', (err, data) => {if (err) {reject(err)         // 通过reject()设置PromiseResult的值} else {resolve(data)}})
})p.then((value) => {           // 把PromiseResult的值取出来,进行相关操作console.log(value.toString())
}, (reason) => {console.log(reason)
})

5. Promise工作流程

6. Promise API

6.1 构造函数 Promise(excutor)

excutor函数:执行器, (resolve, reject) => {}

resolve函数:内部定义成功后调用的函数

reject函数:内部定义失败后调用的函数

构造函数会在Promise立即同步调用,异步操作在执行器中执行

let p = new Promise((resolve, reject) => {console.log(1)
})console.log(2)// 先输出1,再输出2

6.2 Promise.prototype.then方法

语法:promise.then(onResolved, onRejected)

onResolved函数:成功的回调函数, value => {}

onRejected函数:失败的回调函数, reason => {}

返回新的Promise对象

6.3 Promise.prototype.catch方法

与上面的then()类似,不过只能指定失败的回调函数

6.4 Promise.resolve方法

作用:接受一个参数,返回一个成功或失败的Promise对象。能够快速封装一个值,将这个值转化为Promise对象

  • 如果传入的参数是非Promise类型的对象,如字符串、数字等,则返回的结果是成功的Promise对象

  • 如果传入的参数是Promise对象,则参数的结果决定resolve的结果,即参数是成功的Promise对象的话,resolve的结果是成功的,反之是失败的

const p1 = Promise.resolve(123) // Promise { 123 }console.log(p1)const p2 = Promise.resolve(p1) // 参数为成功的Promise对象console.log(p2)const p3 = Promise.resolve(new Promise((resolve, reject) => { // 参数为失败的Promise对象reject('Error')
}))p3.catch(reason => {console.log(reason)
})

6.5 Promise.reject方法

接受一个参数,返回一个失败的Promise对象

const p1 = Promise.reject(123)
console.log(p1)const p2 = Promise.reject(new Promise((resolve, reject) => {resolve('传参为成功的Promise对象')
}))console.log(p2)

6.5 Promise.all方法

参数:promises,promise的数组

返回一个新的Promise,当所有的promise都成功才成功,且结果为成功的结果组成的数组;有一个失败就直接失败,返回的结果就是失败的那一个的结果

const p1 = new Promise((resolve, reject) => {resolve('p1: OK')
})
const p2 = Promise.resolve('p2: OK')
const result1 = Promise.all([p1, p2]) // 所有Promise的结果都成功
console.log(result1)const p3 = Promise.resolve('p3: OK')
const p4 = Promise.reject('p4: Err')
const p5 = Promise.reject('p5: Err')
const result2 = Promise.all([p3, p4, p5]) // 有Promise的结果失败
console.log(result2)

如果想要捕捉异常,直接链式调用即可

const p3 = Promise.resolve('p3: OK')
const p4 = Promise.reject('p4: Err')
const p5 = Promise.reject('p5: Err')
const result2 = Promise.all([p3, p4, p5])
console.log(result2)result2.catch(reason => {console.log(reason)
})

6.6 Promise.race方法

参数:promises,promise的数组

返回一个新的Promise,第一个完成的结果是成功则成功,反之则失败

const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('p1: OK')})
})
const p2 = Promise.reject('p2: Err')
const result1 = Promise.race([p1, p2])
console.log(result1) // [[PromiseResult]]: "p2: Err"result1.catch(reason => {console.log(reason)
})

学习视频:尚硅谷Web前端Promise教程从入门到精通

Promise学习笔记(一)相关推荐

  1. Promise学习笔记

    一.异步任务的处理 这里我从一个实际的例子来作为切入点: 我们调用一个函数,这个函数中发送网络请求(我们可以用定时器来模拟): 如果发送网络请求成功了,那么告知调用者发送成功,并且将相关数据返回过去: ...

  2. Promise 学习笔记

    目录 1. Promise 基本结构 2. Promise 状态和值 3. Promise 的 then 方法 4. Promise基本实现 5. Promise零碎知识 Promise 用法 :MD ...

  3. Promise学习笔记一

    一.简介 1)抽象表达: Promise是一门新的技术(ES6规范) Promise是JS中进行异步编程的新解决方法 2)具体表达: 从语法上来说:Promise是一个构造函数 从功能上来说:Prom ...

  4. Promise学习笔记(上)

    Promise简介 es6引入的异步编程解决方案,从语法上来说就是一个构造函数可以封装异步的任务,并且对结果进行处理.最大的优点是能解决回调地狱问题,同时在对错误处理也更加灵活方便 常见的异步操作有: ...

  5. Promise学习笔记(下)

    自定义封装promise Promise整体 //声明构造函数 class Promise {//构造函数constructor(executor) {}//thenthen (onResolved, ...

  6. ES6基础5(Promise)-学习笔记

    文章目录 ES6基础5(Promise)-学习笔记 Promise 三个状态 状态转换 手写Promise源码 同步异步概念 jquery中 串行并行 async-await 微任务 宏任务 ES6基 ...

  7. JavaScript:学习笔记(9)——Promise对象

    JavaScript:学习笔记(9)--Promise对象 引入Promise Primose是异步编程的一种解决方案,比传统的解决方案回调函数和事件更加合理和强大.如下面为基于回调函数的Ajax操作 ...

  8. 【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(二、JavaScript 异步编程)

    [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程.手写 Promise(课前准备) [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步 ...

  9. 7 种 Javascript 常用设计模式学习笔记

    7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...

最新文章

  1. kernel笔记——块I/O
  2. 浅谈前后端分离思想对自由泳练习的指导意义
  3. KVM虚拟机相关步骤
  4. 用JoyToKey使游戏手柄变键盘或鼠标
  5. RMQ问题:与众不同(st表的高端应用)
  6. 十六进制表示_教资信息技术之:十进制(正数)转二进制、八进制、十六进制...
  7. 介绍一种 Python 更方便的爬虫代理池实现方案
  8. JDK源码系列(6)-StringBuilder
  9. [ActionScript 3.0] 记录几个ByteArray 十六进制 String等相互转换的方法
  10. H3C DHCP中继实验
  11. 解决apicloud中真机同步海马玩模拟器中每次都要升级apploader的问题
  12. 程序猿必看10本好书推荐
  13. C++ 使用replace()方法替换字符串中的反斜杠:左斜杠(\)和右斜杠(/)
  14. 【HBUOJ】暴躁的阿生
  15. [音乐] 逆转裁判1~6【五分半无缝衔接】追求组曲
  16. 云服务器如何重新装系统,云服务器可以重新安装系统
  17. 隐马尔可夫模型-三个盒子颜色序列概率计算问题
  18. 动态规划范例——驿站马车问题
  19. bzoj3323【scoi2013】多项式的运算
  20. 湖南2018年通信工程师现场审核时间|地点|材料

热门文章

  1. 【单调队列】数据结构之单调队列详解
  2. 梯度下降法的三种形式BGD(批量梯度下降)、SGD(随机梯度下降)以及MBGD(小批量梯度下降)
  3. Linux 正则表达式
  4. unity物体设置透明度_URP自学笔记5. 透明度混合与透明度测试
  5. 官宣 | MTC旗下「睿本云」获近5000万元A轮融资,光云科技领投
  6. 基于mysql+php099房屋销售管理系统
  7. 用CHCP命令切换CMD中英文帮助
  8. 基于树莓派的Scratch儿童编程环境定制
  9. 父子组件通信——模拟12306购票添加乘车人
  10. 微软培训于苏州独墅湖