Promise学习

news/2024/9/23 6:37:22/

01_准备_函数对象VS实例对象.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>准备_函数对象 VS 实例对象</title>
</head>
<body>
<script>/*函数对象 VS 实例对象1. 函数对象:将函数作为对象使用时,简称为函数对象。2. 实例对象:new 构造函数或类产生的对象,我们称之实例对象。*/// 函数对象function Person(name, age) {this.name = namethis.age = age}Person.a = 1console.log(Person.a) // 1Person.name = "张三" // 将 Person 看成一个对象console.log(Person.name) // 输出 Person ==> 原因:Person 对象中的 name 属性是只读属性,不可修改!const p1 = new Person("张三", 18) // p1 是 Person 的实例对象console.log(p1)
</script>
</body>
</html>

02_准备_回调函数的分类.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>准备_回调函数的分类</title>
</head>
<body>
<script>/*前序知识:什么是回调?--- 我们定义的,我们没有调用,最终执行了。1. 同步的回调函数理解:立即在主线程上执行,不会放入回调队列中。例子:数组遍历相关的回调函数 / Promise 的 executor 函数。2. 异步的回调函数理解:不会立即执行,会放入回调队列中以后执行。(以后执行:主线程忙完后,再执行回调队列中的回调)例子:定时器回调 / Ajax 回调 / Promise 的成功、失败的回调*/// 同步的回调函数let arr = [1, 3, 5, 7, 9]arr.forEach((item) => {console.log(item)})console.log('主线程的其它代码')// 异步的回调函数setTimeout(() => {console.log('@')}, 0)console.log('主线程...')
</script>
</body>
</html>

03_准备_js中的error.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>准备_js中的error</title>
</head>
<body><script>/*JS 中的错误(Error)和错误处理1. 错误的类型Error:所有错误的父类型ReferenceError:引用的变量不存在TypeError:数据类型不正确RangeError:数据值不在其所允许的范围内--死循环SyntaxError:语法错误2. 错误处理捕获错误:try {} catch () {}抛出错误:throw error3. 错误对象message 属性:错误相关信息stack 属性:记录信息*/// ReferenceError:引用的变量不存在// Uncaught => 未被捕获的/*console.log(a) // Uncaught ReferenceError: a is not defined*/// TypeError:数据类型不正确/*const demo = () => {}demo()() // Uncaught TypeError: demo() is not a function*/// RangeError:数据值不在其所允许的范围内/*const demo = () => {demo()}demo() // Uncaught RangeError: Maximum call stack size exceeded => 超过最大调用堆栈大小*/// SyntaxError:语法错误/*console.log(1 // Uncaught SyntaxError: missing ) after argument list*/// 如何捕获一个错误?// try 中放可能出现错误的代码,一旦出现错误立即停止 try 中代码的执行,调用 catch,并携带错误信息。/*try {console.log(1)console.log(a)console.log(2)} catch (e) {console.log('代码执行出错了,错误的原因是:', e)}*/// 如何抛出一个错误?function demo() {const date = Date.now()if (date % 2 === 0) {console.log('偶数,可以正常工作');} else {throw new Error('奇数,不可以工作!')}}try {demo();} catch (error) {// debugger;console.log('@', error)}</script>
</body>
</html>

04_初识promise.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>初识promise</title>
</head>
<body>
<!--Promise 是什么?1. 抽象表达:(1). Promise 是一门新的技术(ES6 提出的)。(2). Promise 是 JS 中异步编程的新方案(旧方案是谁?--- 纯回调(如:ajax、事件绑定函数))。2. 具体表达:(1). 从语法上来说:Promise 是一个内置构造函数。(构造函数 => 通过 new 关键字创建对象)。(2). 从功能上来说:Promise 的实例对象可以用来封装一个异步操作,并可以获取其 成功/失败 的值。-->
<script type="text/javascript">/*1. Promise 不是回调,是一个内置的构造函数,是程序员自己 new 调用的。2. new Promise 的时候,要传入一个回调函数,它是同步的回调,会立即在主线程上执行,它被称为 executor 函数。3. 每一个 Promise 实例都有 3 种状态,分别是:初始化(pending)、成功(fulfilled)、失败(rejected)4. 每一个 Promise 实例在刚被 new 出来的那一刻,状态都是初始化(pending)5. executor 函数会接收到 2 个参数,它们都是函数,分别用形参:resolve、reject 接收(1). 调用 resolve,会让 Promise 实例状态变为:成功(fulfilled),同时可以指定成功的 value(2). 调用 reject,会让 Promise 实例状态变为:失败(rejected),同时可以指定失败的 reason(3). Promise实例状态只能被修改一次, 修改之后, 将不能被改变*/// 创建一个 Promise 实例对象const p = new Promise((resolve, reject) => {resolve('ok')})console.log('@', p) // 一般不把 Promise 实例做控制台输出
</script>
</body>
</html>

05_Promise基本使用.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Promise基本使用</title>
</head>
<body>
<!--1. 重要语法:new Promise(executor) 构造函数Promise.prototype.then 方法2. 基本编码流程:1. 创建 Promise 的实例对象(pending 状态),传入 executor 函数。2. 在 executor 中启动异步任务(定时器、Ajax 请求)3. 根据异步任务的结果,做不同处理:3.1 如果异步任务成功了:我们调用 resolve(value),让 Promise 实例对象状态变为成功(fulfilled),同时指定成功的 value3.2 如果异步任务失败了:我们调用 reject(reason),让 Promise 实例对象状态变为失败(rejected),同时指定失败的 reason4. 通过 then 方法为 Promise 的实例指定成功、失败的回调函数,来获取成功的 value、失败的 reason注意:then 方法所指定的:成功的回调、失败的回调,都是异步的回调。3. 关于状态的注意点:1. 三个状态:pending:未确定的---初始状态fulfilled:成功的---调用 resolve() 后的状态rejected:失败的----调用 reject() 后的状态2. 只有两种状态改变:pending ==> fulfilledpending ==> rejected3. 状态只能改变一次!!4. 一个 promise 指定多个 成功/失败 回调函数,都会调用吗? ==> 都会调用,全都要(队列)-->
<script type="text/javascript">const p = new Promise((resolve, reject) => {/*setTimeout(() => {resolve('我是成功的数据...')}, 2000)*/// 真正开启一个异步任务const xhr = new XMLHttpRequest()xhr.onreadystatechange = () => {//readyState为4代表接收完毕,接收的可能是:服务器返回的成功数据、服务器返回的错误if (xhr.readyState === 4) {if (xhr.status === 200) resolve(xhr.response)else reject(xhr.response)}}xhr.open('GET', 'https://api.apiopen.top/api/getShortVideo?page=0&size=10')xhr.responseType = "json"xhr.send()})p.then( // 调用p的then方法, 为promise实例对象指定成功的回调和失败的回调(value) => { // 成功的回调-异步console.log('成功了1', value)},(reason) => { // 失败的回调-异步console.log('失败了1', reason)})p.then( // 调用p的then方法, 为promise实例对象指定成功的回调和失败的回调(value) => { // 成功的回调-异步console.log('成功了2', value)},(reason) => { // 失败的回调-异步console.log('失败了2', reason)})console.log("主程序。。。")
</script>
</body>
</html>

06_封装一个简单的Ajax(纯回调).html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>封装一个简单的Ajax</title>
</head>
<body>
<script type="text/javascript">/*定义一个 sendAjax 函数,对 xhr 的 get 请求进行封装:1. 该函数接收两个参数:url(请求地址)、data(参数对象)2. 该函数返回一个 Promise 实例:(1). 若 Ajax 请求成功,则 Promise 实例成功,成功的 value 是返回的数据。(2). 若 Ajax 请求失败,则 Promise 实例失败,失败的 reason 是错误提示。*/function sendAjax(url, data) {return new Promise((resolve, reject) => {// 实例 xhrconst xhr = new XMLHttpRequest()// 绑定监听xhr.onreadystatechange = () => {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) resolve(xhr.response)else reject('请求出了点问题')}}// 整理参数let str = ''for (let key in data) {str += `${key}=${data[key]}`}str = str.slice(0, -1)xhr.open('GET', url + '?' + str)xhr.responseType = 'json'xhr.send()})}const x = sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 10})x.then((value) => {console.log(value)}, (reason) => {console.log(reason)})
</script>
</body>
</html>

07_Promise的API.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Promise的API</title>
</head>
<body>
<!--1. Promise 构造函数:new Promise(executor) {}executor 函数:是同步执行的,(resolve, reject) => {}resolve 函数:调用 resolve 将 Promise 实例内部状态改为成功(fulfilled)reject 函数:调用 reject 将 Promise 实例内部状态改为失败(rejected)说明:executor 函数会在 Promise 内部立即同步调用,异步代码放在 executor 函数中。2. Promise.prototype.then 方法: Promise 实例.then(onFulfilled, onRejected)onFulfilled:成功的回调函数 (value) => {}onRejected:失败的回调函数 (reason) => {}特别注意(难点):then 方法会返回一个新的 Promise 实例对象。3. Promise.prototype.catch 方法:Promise 实例.catch(onRejected)onRejected:失败的回调函数 (reason) => {}说明:catch 方法是 then 方法的语法糖,相当于:then(undefined, onRejected)4. Promise.resolve 方法:Promise.resolve(value)说明:用于快速返回一个状态为 fulfilled 或 rejected 的 Promise 实例对象备注:value 的值可能是:(1)非 Promise 值  (2) Promise 值特别注意:在使用Promise.resolve(value)时, 如果value传的是一个Promise值,并且传过去的Promise失败了, 那么Promise.resolve(value)也会失败5. Promise.reject 方法:Promise.reject(reason)说明:用于快速返回一个状态必为 rejected 的 Promise 实例对象6. Promise.all 方法:Promise.all(promiseArr)promiseArr:包含 n 个 Promise 实例的数组说明:返回一个新的 Promise 实例,只有所有的 promise 都成功才成功,只要有一个失败了就直接失败。7. Promise.race 方法:Promise.race(promiseArr)promiseArr:包含 n 个 Promise 实例的数组说明:返回一个新的 Promise 实例,成功还是失败?以最先出结果的 promise 为准-->
<script type="text/javascript">// 验证:then 方法会返回一个新的 Promise 实例对象。(暂且不研究返回的这个新Promise实例状态怎么变化,后面再研究)/*const p = new Promise((resolve, reject) => {setTimeout(() => {resolve('ok')}, 1000)})const x = p.then((value) => {console.log(value)}, (reason) => {console.log(reason)})console.log('555', x, x===p) // x打印为Promise, 并且不等于p, 说明then的返回值是个新的Promise对象*/// Promise.prototype.catch 方法/* 补充:1. 调用p.catch(f2),其实是等价于调用p.then(undefined,f2),可以方便的指定(Promise)p实例失败的回调,而不须指定p实例成功的回调2. 每次调用p.then() 或 p.catch(), 都会往p实例的回调队列中塞进去一组回调(成功回调f1+失败回调f2),如果p实例失败了, 则会从回调队列中遍历所有组的失败回调,如果其中任何一组中没有指定失败回调, 则都会将异常抛在控制台上如果p实例成功了, 则会从回调队列中遍历所有组的成功回调,如果其中任何一组没有指定成功回调,则就不管了,因为成功了,又没指定成功的回调, Promise认为不需要再处理了*//*const p = new Promise((resolve, reject) => {setTimeout(() => {reject(-100)}, 1000)})p.then(undefined, // 就占个位, 也可以写其它的, 建议写undefinedreason => {console.log('失败了1', reason)})p.catch(reason => {console.log('失败了2', reason)})*/// Promise.resolve/*const p = new Promise((resolve, reject) => {resolve(100)})*//*const p0 = Promise.reject(-100)const p = Promise.resolve(p0)p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})*/// Promise.reject/*const p0 = Promise.resolve(100)const p = Promise.reject(p0)p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})*/// Promise.all/*const p1 = Promise.resolve('a')const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject('b')}, 2000)})const p3 = new Promise((resolve, reject) => {setTimeout(() => {reject('c')}, 100)})const p = Promise.all([p1, p2, p3])p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})*/// Promise.race/*const p1 = Promise.resolve('a')const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject('b')}, 2000)})const p3 = new Promise((resolve, reject) => {setTimeout(() => {reject('c')}, 100)})const p = Promise.race([p1, p2, p3])p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})*/</script>
</body>
</html>

08_promise的几个关键问题_改变Promise实例的状态.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>如何改变一个Promise实例的状态</title>
</head>
<body>
<!--1. 如何改变一个 Promise 实例的状态?(1). 执行 resolve(value):如果当前是 pending 就会变成 fulfilled(2). 执行 reject(reason):如果当前是 pending 就会变成 rejected(3). 执行器函数(executor)抛出异常:如果当前是 pending 就会变成 rejected-->
<script type="text/javascript">const p = new Promise((resolve, reject) => {// console.log(a) // 引擎抛出异常throw 999 // 编码抛异常})p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})
</script>
</body>
</html>

09_promise的几个关键问题_状态VS回调.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>改变Promise实例的状态和指定回调函数谁先谁后?</title>
</head>
<body>
<!--改变 Promise 实例的状态和指定回调函数谁先谁后?1. 都有可能,正常情况下是先指定回调再改变状态,但也可以先改状态再指定回调。2. 如何先改状态再指定回调?延迟一会再调用 then()3. Promise 实例什么时候才能得到数据?如果先指定的回调(放在 Promise 实例的身上 p.list),那当状态发生改变时,回调函数就会推向队列,然后被调用,得到数据如果先改变的状态(会存储状态),那当指定回调时,回调函数就会立即被推向队列,然后被调用(回调不会在实例身上存储一份了,存储就太无聊了),得到数据-->
<script type="text/javascript">// 先指定回调,后改变状态(最常见)/*const p = new Promise((resolve, reject) => {setTimeout(() => {resolve('ok')}, 2000) // 这个任务会放入浏览器定时管理模块(比如: 还有ajax异步请求模块), 等到2s之后, 将此任务推入队列等待主线程忙完之后调用})p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})*/// 先改变状态,后指定回调/*const p = new Promise((resolve, reject) => {reject('err')})setTimeout(() => { // 2s之后,再指定回调// (因为p的状态已经改了, 所以这里不会再往p对象的回调队列中再塞一组回调等待状态改变再推入浏览器异步任务队列等待主线程忙完调用了,//  而是直接推入浏览器异步任务队列等待主线程忙完再调用了)p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})}, 2000)setTimeout(() => { // 我在3s之后,再次指定一组回调p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})}, 3000)*/
</script>
</body>
</html>

10_then的链式调用.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>then的链式调用</title>
</head>
<body>
<!--Promise 实例.then() 返回的是一个【新的 Promise 实例】,它的值和状态由什么决定?1. 简单表达:由 then() 所指定的回调函数执行的结果决定(因为then中可以指定成功的回调和失败的回调这2种函数,这里指的回调函数这2种都包括)。2. 详细表达:(1). 如果 then 所指定的回调返回的是非 Promise 值a:那么【新 Promise 实例】状态为:成功(fulfilled),成功的 value 为 a注意:非 Promise 值包括:空数组[],空对象{},字符串,false,undefined....(2). 如果 then 所指定的回调返回的是一个 Promise 实例p:那么【新 Promise 实例】的状态、值,都与 p 一致。(3). 如果 then 所指定的回调抛出异常:那么【新 Promise 实例】状态为 rejected,reason 为抛出的那个异常-->
<script type="text/javascript">const p = new Promise((resolve, reject) => {setTimeout(() => {reject('出现了异常')}, 1000)})p.then(value => {console.log('成功了1', value)},reason => {console.log('失败了1', reason)return Promise.resolve('ok')}).then(value => {console.log('成功了2', value)throw 999},reason => {console.log('失败了2', reason)}).then(value => {console.log('3成功了', value)},reason => {console.log('3失败了', reason)})</script>
</body>
</html>

11_使用then的链式调用解决回调地狱.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>使用then的链式调用解决回调地狱</title>
</head>
<body>
<script type="text/javascript">// Promise 如何串连多个异步任务?------通过 then 的链式调用function sendAjax(url, data) {return new Promise((resolve, reject) => {// 实例 xhrconst xhr = new XMLHttpRequest()// 绑定监听xhr.onreadystatechange = () => {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) resolve(xhr.response)else reject('请求出了点问题')}}// 整理参数let str = ''for (let key in data) {str += `${key}=${data[key]}`}str = str.slice(0, -1)xhr.open('GET', url + '?' + str)xhr.responseType = 'json'xhr.send()})}// 发送第 1 次请求sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5}).then(value => {console.log('第1次请求成功了', value)return sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})},reason => {console.log('第1次请求失败了', reason)}).then(value => {console.log('第二次请求成功了', value)return sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})},reason => {console.log('第二次请求失败了', reason)}).then(value => {console.log('第三次请求成功了', value)},reason => {console.log('第三次请求失败了', reason)})
</script>
</body>
</html>

12_中断Promise链.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>中断Promise链</title>
</head>
<body>
<!--中断 Promise 链:(1). 当使用 Promise 的 then 链式调用时,在中间中断,不再调用后面的回调函数。(2). 办法:在失败的回调函数中返回一个 pending 状态的 Promise 实例。即 return new Promise(() => {})
-->
<script type="text/javascript">// Promise 如何串连多个异步任务?------通过 then 的链式调用function sendAjax(url, data) {return new Promise((resolve, reject) => {// 实例 xhrconst xhr = new XMLHttpRequest()// 绑定监听xhr.onreadystatechange = () => {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) resolve(xhr.response)else reject('请求出了点问题')}}// 整理参数let str = ''for (let key in data) {str += `${key}=${data[key]}`}str = str.slice(0, -1)xhr.open('GET', url + '?' + str)xhr.responseType = 'json'xhr.send()})}// 发送第 1 次请求sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5}).then(value => {console.log('第1次请求成功了', value)return sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})},reason => {console.log('第1次请求失败了', reason)return new Promise(() => {}) // 返回一个状态为pending状态的Promise实例,外面这个then返回就是就是这个pending状态的Promise实例,就不会调用成功或失败的回调了}).then(value => {console.log('第二次请求成功了', value)return sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})},reason => {console.log('第二次请求失败了', reason)return new Promise(() => {})}).then(value => {console.log('第三次请求成功了', value)},reason => {console.log('第三次请求失败了', reason)return new Promise(() => {})})
</script>
</body>
</html>

13_错误的穿透.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>错误的穿透</title>
</head>
<body>
<!--Promise 错误穿透:(1). 当使用 Promise 的 then 链式调用时,可以在最后用 catch 指定一个失败的回调。(2). 前面任何操作出了错误,都会传到最后失败的回调中处理了。(底层:默认存在 reason => {throw reason} )备注:如果不存在 then 的链式调用,就不需要考虑 then 的错误穿透--><script type="text/javascript">// Promise 如何串连多个异步任务?------通过 then 的链式调用function sendAjax(url, data) {return new Promise((resolve, reject) => {// 实例 xhrconst xhr = new XMLHttpRequest()// 绑定监听xhr.onreadystatechange = () => {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) resolve(xhr.response)else reject('请求出了点问题')}}// 整理参数let str = ''for (let key in data) {str += `${key}=${data[key]}`}str = str.slice(0, -1)xhr.open('GET', url + '?' + str)xhr.responseType = 'json'xhr.send()})}// 发送第 1 次请求sendAjax('https://api.apiopen.top/api/getHaoKanVideo1', {page: 2, size: 5}).then(value => {console.log('第1次请求成功了', value)return sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})},// reason => {//     console.log('第1次请求失败了', reason)//     return new Promise(() => {//     })// }).then(value => {console.log('第二次请求成功了', value)return sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})},// reason => {//     console.log('第二次请求失败了', reason)//     return new Promise(() => {//     })// }).then(value => {console.log('第三次请求成功了', value)},// reason => {//     console.log('第三次请求失败了', reason)//     return new Promise(() => {//     })// }).catch(reason => {console.log('兜底的catch', reason)})
</script>
</body>
</html>

13_错误的穿透2.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>错误的穿透</title>
</head>
<body>
<!--Promise 错误穿透:(1). 当使用 Promise 的 then 链式调用时,可以在最后用 catch 指定一个失败的回调。(2). 前面任何操作出了错误,都会传到最后失败的回调中处理了。(底层:默认存在 reason => {throw reason} )备注:如果不存在 then 的链式调用,就不需要考虑 then 的错误穿透--><script type="text/javascript">// 另一个例子演示错误的穿透const p = new Promise((resolve, reject) => {setTimeout(() => {resolve(-1)}, 1000)})p.then(value => {console.log('成功了1', value)throw 999},// 如果不写,程序底层会自动加上reason => {throw reason}).then(value => {console.log('成功了2', value)return Promise.reject(-888)},reason => {console.log('123')throw reason}).catch(reason => {console.log('失败了', reason)})
</script>
</body>
</html>

14_Promise的优势.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Promise的优势</title>
</head>
<body>
<!--Promise 的优势:1. 指定回调函数的方式更加灵活:旧的:必须在启动异步任务之前指定Promise流程:启动异步任务 => 返回 Promise 实例对象 => 给 Promise 对象绑定回调函数(甚至可以在异步任务结束后再指定回调函数)2. 支持链式调用,可以解决回调地狱问题(1). 什么是回调地狱?回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件(2). 回调地狱的弊病:代码不便于阅读、不便于异常的处理(3). 一个不是很优秀的解决方案:then 的链式调用(4). 终极解决方案:async / await(ES7提出的, 底层实际上依然使用 then 的链式调用)-->
</body>
</html>

15_async与await的使用.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>async与await的使用</title>
</head>
<body>
<!--1. async 修饰的函数函数的返回值为 Promise 对象Promise 实例的结果由 async 函数执行的返回值决定当原函数返回的是非Promise值时, 则为成功, 成功的值就是返回的Promise值当原函数返回的时Promise值时, 则状态与该Promise保持一致, 值为该Promise成功或失败的值2. await 表达式:await 右侧的表达式一般为 Promise 实例对象,但也可以是其它的值(1). 如果表达式是 Promise 实例对象,await 后的返回值是 promise 成功的值(2). 如果表达式是其它值,直接将此值作为 await 的返回值3. 注意:await 必须写在 async 函数中,但 async 函数中可以没有 await如果 await 的 Promise 实例对象失败了,就会抛出异常,需要通过 try...catch 来捕获异常-->
<script type="text/javascript">const p = new Promise((resolve, reject) => {setTimeout(() => {resolve('ok~')}, 1000)})const p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('ok2~')}, 1000)})// p.then()用法/*p.then(value => {console.log('成功了', value)},reason => {console.log('失败了', reason)})*/// async await// 注意:最前面有分号 ; (叹号 ! 也可以);const a = (async () => {try {const result = await p // 一直等到p这个Promise实例成功了之后,获取到p成功的值才赋给result, 否则就一直等,// 或者p这个Promise实例失败了,那么这里就会抛出异常, 可以考虑使用try-catch包裹它作失败处理,// 如果不考虑失败的情况, 也可以不作处理console.log(result)const res = await p2console.log(res)} catch(e) {console.log(e)}})()a.then(value => {console.log('ok', value)},reason => {console.log('err', reason)})</script>
</body>
</html>

16_await的应用.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>await的应用</title>
</head>
<body>
<script type="text/javascript">/*function demo1() {return Promise.reject('a');}const p = demo1()console.log(p)async function demo2() {return Promise.resolve('b')}const p2 = demo2()console.log('p2',p2) // 直接打印p2, 还是pending, 其实不应该直接打印, 应该使用then去接结果p2.then(res => {console.log('res', res)}, err => {console.log('err', err)});console.log('111')*/function sendAjax(url, data) {return new Promise((resolve, reject) => {// 实例 xhrconst xhr = new XMLHttpRequest()// 绑定监听xhr.onreadystatechange = () => {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) resolve(xhr.response)else reject('请求出了点问题')}}// 整理参数let str = ''for (let key in data) {str += `${key}=${data[key]}`}str = str.slice(0, -1)xhr.open('GET', url + '?' + str)xhr.responseType = 'json'xhr.send()})}sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5}).then(value => {console.log('第1次请求成功了', value)}).then(value => {console.log('第2次请求成功了', value)}).then(value => {console.log('第3次请求成功了', value)});(async () => { // 立即调用函数前面最好都加上分号try {// 第一次发送请求const res1 = await sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})console.log('第1次请求成功了', res1)// 第二次发送请求const res2 = await sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})console.log('第2次请求成功了', res2)// 第三次发送请求const res3 = await sendAjax('https://api.apiopen.top/api/getHaoKanVideo', {page: 2, size: 5})console.log('第3次请求成功了', res3)} catch (e) {console.log(e)}})()</script>
</body>
</html>

17_await的原理.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>await的原理</title>
</head>
<body>
<!--若我们使用 async 配合 await 这种写法:1. 表面上不出现任何的回调函数2. 但实际上底层把我们写的代码进行了加工,把回调函数“还原”回来了。3. 最终运行的代码依然有回调,只是程序员没有看见-->
<script type="text/javascript">const p = new Promise((resolve, reject) => {setTimeout(() => {resolve('ok')}, 4000)})async function demo() {// 程序员“轻松”的写法const res = await pconsole.log(res)console.log(666)// 浏览器翻译后的代码/*p.then(res => {console.log(res)console.log(666)})*/}demo()console.log(123) // 所以会先输出123, 然后是ok、666
</script>
</body>
</html>

18_宏队列与微队列.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>宏队列VS微队列</title>
</head>
<body>
<!--宏队列:[宏任务1, 宏任务2 ...](宏任务有 定时器 ajax onclick....)微队列:[微任务1, 微任务2 ...](微任务现在仅有 Promise)规则:每次要执行宏队列里的一个任务之前,先看微队列里是否有待执行的微任务1. 如果有,先执行微任务2. 如果没有,按照宏队列里任务的顺序,依次执行(可能会出现新的微任务,规则不变,微任务先执行)-->
<script type="text/javascript">// 代码一/*setTimeout(() => { // 主线程将此任务交给浏览器定时管理模块, 0s后, 定时管理模块将此任务推入宏队列(异步回调,就是要进入队列等待主线程忙完再执行),// 但是主线程此时还没忙完, 因此该宏任务需要等到主线程忙完才会处理console.log('timeout')}, 0)Promise.resolve(1).then( // 这里是先改了Promise实例的状态, 然后为Promise实例指定了成功的回调(异步回调), Promise模块将此回调立即交给微队列(因为Promise状态此时已经确定了),// 但是主线程此时仍没有忙完, 因此该微任务需要等到主线程忙完才会处理// (但是微任务的优先级永远比宏任务优先级要高,执宏任务前先看有没有行微任务)value => {console.log('成功1', value)})Promise.reject(2).catch(reason => {console.log('失败2', reason)})console.log('主程序')*/// 结果:主程序  成功1  失败2  timeout// 宏队列:timeout// 微队列:成功1 失败2// 代码二/*setTimeout(() => {console.log('timeout1')})setTimeout(() => {console.log('timeout2')})Promise.resolve(1).then(value => {console.log('成功1', value)})Promise.reject(2).catch(reason => {console.log('失败2', reason)})*/// 结果:成功1 失败2 timeout1 timeout2// 宏队列:timeout1 timeout2// 微队列:成功1 失败2// 代码三setTimeout(() => {console.log('timeout1')Promise.resolve(5).then(value => {console.log('成功5', value)})})setTimeout(() => {console.log('timeout2')})Promise.resolve(1).then(value => {console.log('成功1', value)})Promise.reject(4).catch(reason => {console.log('失败4', reason)})// 结果:成功1 失败4 timeout1 成功5 timeout5// 宏队列:(timeout1 成功5) timeout5// 微队列: 成功1 失败4
</script>
</body>
</html>

19_面试题.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>面试题</title>
</head>
<body>
<script type="text/javascript">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)})}).then(() => {console.log(6)})new Promise((resolve, reject) => {console.log(7)resolve()}).then(() => {console.log(8)})// 172384650
</script>
</body>
</html>

http://www.ppmy.cn/news/4527.html

相关文章

jdk11新特性——更简化的编译运行程序

目录一、概述二、注意事项三、注意事项1——代码示例3.1、示例13.2、示例23.3、示例3四、注意事项2——代码示例4.1、示例14.2、示例2一、概述 JEP 330 : 增强java启动器支持运行单个java源代码文件的程序。 在我们的认知里面&#xff0c;要运行一个 Java 源代码必须先编译&am…

基于Java毕业设计新疆旅游专列订票系统源码+系统+mysql+lw文档+部署软件

基于Java毕业设计新疆旅游专列订票系统源码系统mysqllw文档部署软件 基于Java毕业设计新疆旅游专列订票系统源码系统mysqllw文档部署软件本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 开发软件&#xff1a;idea eclipse 前端技术&a…

能够让你装逼的10个Python小技巧

列表推导式 你有一个list&#xff1a; bag [1, 2, 3, 4, 5] 现在你想让所有元素翻倍&#xff0c;让它看起来是这个样子&#xff1a; [2, 4, 6, 8, 10] 大多初学者&#xff0c;根据之前语言的经验会大概这样来做 bag [1, 2, 3, 4, 5] for i in range(len(bag)): bag[i] ba…

STM32 10个工程实战前言

从今年2022年元旦开通博客到现在基本接近一年了&#xff0c;真的会感到感觉时间飞逝&#xff0c;尤其当你全身心地投入一件工作上时&#xff0c;在FPGA基础篇和FPGA 20个经理例程篇后&#xff0c;又准备了STM32基础篇和STM32 10个工程实战篇&#xff0c;前两者即将收尾&#xf…

DCBC路由模式配置端口映射

DCBC路由模式配置端口映射 拓扑搭建 前提&#xff1a;使用DCBC、CS6200、两台PC机&#xff1a;一台用户配置IP另一台用于测试端口映射&#xff0c;外网环境使用192.168.19.0/24网段 网段划分 全网互通 1.DCBC对应工作模式配置 对应接口配置 配置静态路由两条&#xff0c;一条…

【Flink】Flink Starting Offset 启动消费位置 指定时间消费

文章目录 1.概述2.测试3.源码1.概述 首先参考文章:【Flink】Flink 1.14.0 全新的 Kafka Connector Kafka Source 能够通过指定 OffsetsInitializer来消费从不同偏移量开始的消息。内置的初始值设定项包括: KafkaSource.builder()// Start from committed offset of the co…

[hadoop全分布部署]安装Hadoop、验证Hadoop①

&#x1f468;‍&#x1f393;&#x1f468;‍&#x1f393;博主&#xff1a;发量不足 个人简介&#xff1a;耐心&#xff0c;自信来源于你强大的思想和知识基础&#xff01;&#xff01; &#x1f4d1;&#x1f4d1;本期更新内容&#xff1a;安装Hadoop、验证Hadoop①&#…

【实时数仓】DWM层跳出明细计算之需求分析、读取数据、通过Flink的CEP完成跳出判断、写回kafka、测试

文章目录一 DWM层-跳出明细计算1 需求分析与思路&#xff08;1&#xff09;什么是跳出&#xff08;2&#xff09;计算跳出行为的思路&#xff08;3&#xff09;实现思路2 读取数据&#xff08;1&#xff09;代码编写&#xff08;2&#xff09;测试3 通过Flink的CEP完成跳出判断…