文章目录

  • 前奏
    • 1.函数对象
    • 2.回调函数
    • 3.Error
  • 正题
    • 1.基本使用
    • 2.回调地狱
    • 3.关键问题
    • 4.async与await
  • 异步队列
    • 示例

前奏

1.函数对象

    /* 1. 函数对象与实例对象函数对象: 将函数作为对象使用时, 简称为函数对象实例对象: new 函数产生的对象, 简称为对象*/function Fn() {   // Fn函数 }const fn = new Fn() // Fn是构造函数  fn是实例对象(简称为对象)console.log(Fn.prototype) // Fn是函数对象Fn.call({}) // Fn是函数对象$('#test') // jQuery函数$.get('/test') // jQuery函数对象function Person(params) {}

PS:Fn() 中的Fn为函数,Fn.b中的Fn为对象,只有Fn为函数对象才有bind,apply等方法

原型对象(有点像类)方法,其实例对象可以调用
函数对象调用方法,有点像类调用静态方法

2.回调函数

特点:①自己定义 ②非自己直接调用 ③但执行了
PS:若参数是回调函数,具体得看调用时传的的啥函数

/*1). 同步回调: 理解: 立即执行, 完全执行完了才结束, 不会放入回调队列中例子: 数组遍历相关的回调函数 / Promise的excutor函数2). 异步回调: 理解: 不会立即执行, 会放入回调队列中将来执行例子: 定时器回调 / ajax回调 / Promise的成功|失败的回调*/// 1. 同步回调函数// const arr = [1, 3, 5]arr.forEach(item => { // 遍历回调, 同步回调函数, 不会放入列队, 一上来就要执行完console.log(item)})console.log('forEach()之后')// 2. 异步回调函数setTimeout(() => { // 异步回调函数, 会放入队列中将来执行console.log('timout callback()')}, 0)console.log('setTimeout()之后')

3.Error

    1. 错误的类型Error: 所有错误的父类型ReferenceError: 引用的变量不存在TypeError: 数据类型不正确的错误RangeError: 数据值不在其所允许的范围内SyntaxError: 语法错误2. 错误处理捕获错误: try ... catch抛出错误: throw error对象3. 错误对象message属性: 错误相关信息stack属性: 函数调用栈记录信息

正题

1.基本使用

  /* 1. Promise构造函数: Promise (excutor) {}excutor函数: 同步执行  (resolve, reject) => {}resolve函数: 内部定义成功时我们调用的函数 value => {}reject函数: 内部定义失败时我们调用的函数 reason => {}说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行2. Promise.prototype.then方法: (onResolved, onRejected) => {}onResolved函数: 成功的回调函数  (value) => {}onRejected函数: 失败的回调函数 (reason) => {}说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调返回一个新的promise对象3. Promise.prototype.catch方法: (onRejected) => {}onRejected函数: 失败的回调函数 (reason) => {}说明: then()的语法糖, 相当于: then(undefined, onRejected)4. Promise.resolve方法: (value) => {}value: 成功的数据或promise对象说明: 返回一个成功/失败的promise对象5. Promise.reject方法: (reason) => {}reason: 失败的原因说明: 返回一个失败的promise对象6. Promise.all方法: (promises) => {}promises: 包含n个promise的数组说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败7. Promise.race方法: (promises) => {}promises: 包含n个promise的数组说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态*/// 1. 创建一个新的promise对象const p = new Promise((resolve, reject) => {// 执行器函数  同步回调console.log('执行 excutor')// 2. 可执行同步/异步任务// 3.1. 如果成功了, 调用resolve(value)// 3.2. 如果失败了, 调用reject(reason) })console.log('new Promise()之后') //这句打印主要是判断执行器中的任务是同步还是异步p.then( // 异步执行回调任务value => { // 接收得到成功的value数据    onResolvedconsole.log('成功的回调', value)  },reason => {// 接收得到失败的reason数据  onRejectedconsole.log('失败的回调', reason)}

2.回调地狱

      /* 1. 指定回调函数的方式更加灵活: 旧的: 必须在启动异步任务前指定promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定)2. 支持链式调用, 可以解决回调地狱问题什么是回调地狱? 回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调函数执行的条件回调地狱的缺点?  不便于阅读 / 不便于异常处理解决方案? promise链式调用终极解决方案? async/await*///--------------------------示意----------------------------------------//2.1. 回调地狱doSomething(function(result) {doSomethingElse(result, function(newResult) {doThirdThing(newResult, function(finalResult) {console.log('Got the final result: ' + finalResult)}, failureCallback)}, failureCallback)}, failureCallback)//2.2. 使用promise的链式调用解决回调地狱doSomething().then(function(result) {return doSomethingElse(result)}).then(function(newResult) {return doThirdThing(newResult)}).then(function(finalResult) {console.log('Got the final result: ' + finalResult)}).catch(failureCallback)//2.3. async/await: 回调地狱的终极解决方案async function request() {try {const result = await doSomething()const newResult = await doSomethingElse(result)const finalResult = await doThirdThing(newResult)console.log('Got the final result: ' + finalResult)} catch (error) {failureCallback(error)}}

3.关键问题

问题一:

    /* 1.    如何改变promise的状态?(1)resolve(value): 如果当前是pendding就会变为resolved(2)reject(reason): 如果当前是pendding就会变为rejected(3)抛出异常: 如果当前是pendding就会变为rejected2. 一个promise指定多个成功/失败回调函数, 都会调用吗?当promise改变为对应状态时都会调用*/const p = new Promise((resolve, reject) => {// resolve(1) // promise变为resolved成功状态   若是resolve()虽成功,但值为undifined// reject(2) // promise变为rejected失败状态// throw new Error('出错了') // 抛出异常, promse变为rejected失败状态, reason为 抛出的errorthrow 3 // 抛出异常, promse变为rejected失败状态, reason为 抛出的3})p.then(value => {},reason => {console.log('reason', reason)})p.then(value => {},reason => {console.log('reason2', reason)})

问题二:

/* 3.改变promise状态和指定回调函数谁先谁后?(1)都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调(2)如何先改状态再指定回调?①在执行器中直接调用resolve()/reject()②延迟更长时间才调用then()(3)什么时候才能得到数据?①如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据②如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据*/// 常规: 先指定回调函数, 后改变的状态new Promise((resolve, reject) => {setTimeout(() => {resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数}, 1000);}).then(// 先指定回调函数, 保存当前指定的回调函数value => {},reason => {console.log('reason', reason)})// 如何先改状态, 后指定回调函数new Promise((resolve, reject) => {resolve(1) // 先改变的状态(同时指定数据)}).then(// 后指定回调函数, 异步执行回调函数value => {console.log('value2', value)},reason => {console.log('reason2', reason)})console.log('-------')const p = new Promise((resolve, reject) => {setTimeout(() => {resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数}, 1000);})setTimeout(() => {p.then(value => {console.log('value3', value)},reason => {console.log('reason3', reason)})}, 1100);

问题三:

/* 4.    promise.then()返回的新promise的结果状态由什么决定?(1)简单表达: 由then()指定的回调函数执行的结果决定(2)详细表达:①如果抛出异常, 新promise变为rejected, reason为抛出的异常②如果返回的是非promise的任意值, 新promise变为resolved, value为返回的值③如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果 */new Promise((resolve, reject) => {// resolve(1)reject(1)}).then(value => {console.log('onResolved1()', value)// return 2// return Promise.resolve(3)// return Promise.reject(4)throw 5},reason => {console.log('onRejected1()', reason)// return 2// return Promise.resolve(3)// return Promise.reject(4)throw 5}).then(value => {console.log('onResolved2()', value)},reason => {console.log('onRejected2()', reason)})

问题四:

/* 5.promise如何串连多个操作任务?(1)promise的then()返回一个新的promise, 可以开成then()的链式调用(2)通过then的链式调用串连多个同步/异步任务*/new Promise((resolve, reject) => {setTimeout(() => {console.log("执行任务1(异步)")resolve(1)}, 1000);}).then(value => {console.log('任务1的结果: ', value)console.log('执行任务2(同步)')return 2}).then(value => {console.log('任务2的结果:', value)return new Promise((resolve, reject) => {// 启动任务3(异步)setTimeout(() => {console.log('执行任务3(异步))')resolve(3)}, 1000);})}).then(value => {console.log('任务3的结果: ', value)})

问题五:

/* 6.promise异常传/穿透?(1)当使用promise的then链式调用时, 可以在最后指定失败的回调, (2)前面任何操作出了异常, 都会传到最后失败的回调中处理7.中断promise链?(1)当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数(2)办法: 在回调函数中返回一个pendding状态的promise对象*/new Promise((resolve, reject) => {// resolve(1)reject(1)}).then(value => {console.log('onResolved1()', value)return 2},// reason => {throw reason}).then(value => {console.log('onResolved2()', value)return 3},reason => {throw reason}).then(value => {console.log('onResolved3()', value)},reason => Promise.reject(reason)).catch(reason => {console.log('onReejected1()', reason)// throw reason// return Promise.reject(reason)return new Promise(() => {}) // 返回一个pending的promise  中断promise链}).then(value => {console.log('onResolved3()', value)},reason => {console.log('onReejected2()', reason)})

4.async与await

/*1. async 函数函数的返回值为promise对象promise对象的结果由async函数执行的返回值决定2. await 表达式await右侧的表达式一般为promise对象, 但也可以是其它的值如果表达式是promise对象, await返回的是promise成功的值如果表达式是其它值, 直接将此值作为await的返回值3. 注意:await必须写在async函数中, 但async函数中可以没有await如果await的promise失败了, 就会抛出异常, 需要通过try...catch来捕获处理*/// async函数的返回值是一个promise对象// async函数返回的promise的结果由函数执行的结果决定async function fn1() {return 1// throw 2// return Promise.reject(3)// return Promise.resolve(3)/* return new Promise((resolve, reject) => {setTimeout(() => {resolve(4)}, 1000);}) */}const result = fn1()// console.log(result)result.then(value => {console.log('onResolved()', value)},reason => {console.log('onRejected()', reason)})function fn2() {return new Promise((resolve, reject) => {setTimeout(() => {// resolve(5)reject(6)}, 1000);})}function fn4() {return 6}async function fn3() {try {// const value = await fn2() // await右侧表达为promise, 得到的结果就是promise成功的valueconst value = await fn1()console.log('value', value)} catch (error) {console.log('得到失败的结果', error)}// const value = await fn4() // await右侧表达不是promise, 得到的结果就是它本身// console.log('value', value)}fn3()

异步队列

JS 中用来存储待执行回调函数的队列包含2 个不同特定的列队

JS为单线程引擎,任务的执行顺序:同步任务-》队列中的异步任务(微队列-》宏队列)
PS:
①每个宏队列任务执行前,都要将当前微队列中所有微任务取出先执行。
②定时器达到指定的延迟时间后,才将包含的回调任务放入宏队列。

示例

题一:

      /* 宏: []->[]->[5] ->[5]  ->[5]   -> [5]微: []->[]->[1] ->[1,2]->[1,2] -> []3->3,7->3,7-> 3,7  ->3,7,4 -> 3,7,4,1,2 -> 3 7 4 1 2 5*/const first = () => (new Promise((resolve, reject) => {console.log(3)let p = new Promise((resolve, reject) => {console.log(7)setTimeout(() => {console.log(5)resolve(6) //后面没有onResolved/onRejected回调,没能打印}, 0) //延迟为0,故立即将包含的回调放入宏队列resolve(1)})resolve(2)p.then((arg) => { //p状态成功后,该回调放入微队列console.log(arg)})}))first().then((arg) => {console.log(arg)})console.log(4)

题二:

/*
1,7,2,3,8,4,6,5,0
宏:[0]    ->[0] ->
微:[2,8] ->[8,4]  ->[4,6]       ->[6,5]1,7 ->1,7,2,3 ->1,7,2,3,8 ->1,7,2,3,8,4*/setTimeout(() => {console.log("0")}, 0)new Promise((resolve,reject)=>{console.log("1")resolve()}).then(()=>{        console.log("2")new Promise((resolve,reject)=>{console.log("3")resolve()}).then(()=>{      console.log("4")}).then(()=>{       console.log("5") //在取出“2”异步任务,“3”被同步打印,可获取串连.then中的各回调函数,只不过加入微队列的前提是前一个已完成返回promise对象,否则只是先缓存})}).then(()=>{  console.log("6")})new Promise((resolve,reject)=>{console.log("7")resolve()}).then(()=>{         console.log("8")})

【Promise】基本使用+回调地狱+宏队列与微队列相关推荐

  1. Promise相关内容(三)——异步获取服务器数据:promise方式解决回调地狱的问题。通过多个.then使代码可读性更高 实现异步任务的串行执行,保证按顺序发送请求获取数据

    Promise相关内容(三)--异步获取服务器数据:promise方式解决回调地狱的问题.通过多个.then使代码可读性更高 & 实现异步任务的串行执行,保证按顺序发送请求获取数据 第一种形式 ...

  2. 使用ES6的Promise完美解决回调地狱

    相信经常使用ajax的前端小伙伴,都会遇到这样的困境:一个接口的参数会需要使用另一个接口获取. 年轻的前端可能会用同步去解决(笑~),因为我也这么干过,但是极度影响性能和用户体验. 正常的前端会把接口 ...

  3. vue页面取ajax返回值,Vue前端交互模式、Promise用法(回调地狱)

    Promise 概述Promise 是异步编程的一种解决方案,从语法上讲,Promise 是一个对象,从它可以获取异步操作的消息. 优点:可以避免多层异步调用嵌套问题(回调地狱) Promise 对象 ...

  4. Promise学习——解决回调地狱问题

    Promise promise 容器概念: callback hell(回调地狱): 文件的读取无法判断执行顺序(文件的执行顺序是依据文件的大小来决定的)(异步api无法保证文件的执行顺序) var ...

  5. Promise语法处理回调地狱

    一.什么是回调地狱 setTimeout(function () { //第一层console.log(111);setTimeout(function () { //第二程console.log(2 ...

  6. 回调地狱以及用promise怎么解决回调地狱

    哈哈哈,我又又又回来了,不好意思,最近枸杞喝的比较到位,精力比较旺盛. 现在我们来聊一聊啥是回调地狱,注意是回调地狱啊   不是RB人民最爱拍的那啥地狱啊,来吧,上车吧少年,这是去幼儿园的车 都让开, ...

  7. Promise解决回调地狱写法

    这里可以使用Promise来解决回调地狱的问题! 那么我们这里有一个需求,就是我们需要读取三个 .txt 文件,需要第一个文件读取完成后才能读取第二个文件以此类推. 那么这里来一个Promise的错误 ...

  8. Promise的基础使用与生成器配合Promise解决回调地狱

    经过几天对Promise的了解,希望可以帮助到大家. 什么是回调地狱         说起回调地狱 首先想到的是异步 在js中我们经常会大量使用异步回调,常用的ajxa请求 来看下面这段代码: fun ...

  9. 回调地狱以及解决回调地狱 - promise嵌套变链接 - 解决终极办法 - async 和 await

    回调函数? 当一个函数被当做参数传递时,这个函数就叫做回调函数-  callback 通常使用回调函数来处理异步代码 当异步代码执行结束后,需要执行的代码就要放在回调函数中 回调地狱? 当回调函数嵌套 ...

最新文章

  1. RDKit | 基于RDKit可视化脂溶性在溶解度贡献中的应用
  2. html5.js让IE(包括IE6)支持HTML5元素方法
  3. 十大经典数据挖掘算法:EM
  4. Reporting Area and Available Characteristics
  5. Theano 中文文档 0.9 - 5. 安装Theano
  6. Java中的秒表-StopWatch
  7. 【数据科学】什么是数据分析
  8. pragma pack对齐方式详细介绍
  9. linux脚本中使用转义括号,Linux之shell中的大括号、中括号、小括号的使用详解+多示例...
  10. 中国通信简史 (上)
  11. 【学习教程】CMIP6数据处理方法与典型案例分析
  12. android水下气泡,科学网—水下爆炸气泡的基本现象及规律 - 黄超的博文
  13. Scratch(三十八):八大行星
  14. Unity官方案例之星际航行游戏(Space Shooter)学习总结
  15. 《李航 统计学习方法》学习笔记——第八章提升方法
  16. Linux下服务器基本环境搭建步骤详解(三种软件安装方式)
  17. 在Altium Designer中快速命名多引脚芯片的引脚名称
  18. vr虚拟现实技术介绍,vr虚拟现实技术未来前景
  19. 黑苹果oc清除nvram_黑苹果完善之路-英特尔蓝牙「开启/关闭」功能完善教程
  20. Symfony 入门教程

热门文章

  1. C# 异常处理 浮兮vip解析
  2. enqueue_task和dequeue_task源码分析
  3. 扔掉FPN来做目标检测,YOLOF开源:你只需要看一层特征|CVPR2021
  4. 22款奔驰GLS450升级大柏林音响,驾驶疲劳来个音乐缓解一下
  5. 亥姆霍兹线圈测量系统的测量原理及主要用途
  6. Zwave zniffer 数据通过串口接收
  7. 开篇 - 个人理财课程
  8. SEO新手入门系列2022(七):站内SEO优化
  9. 一分钟复习完CSS基础知识
  10. 泰克示波器采样率设置