Promise
Promise
Echopromise asyan await
1.回调函数的分类
什么是回调:我们定义的,我们没有调用,最终执行了
1.同步的回调函数:
** 理解: 立即在主线程上执行, 不会放入回调队列中。
** **例子: 数组遍历相关的回调函数 **
2.异步的回调函数:
** 理解: 不会立即执行, 会放入回调队列中以后执行
** **例子: 定时器回调 / ajax回调 **
异步回调一般都是需要时间的,像定时器,成功结果的回调和失败结果的回调这种一般都是异步回调
2.控制台遇到的错误以及分析
2.1常见的错误类型
- Erroe :是所有错误类型的父类
进一步理解JS中的错误(Error)和错误处理
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error
ReferenceError: 引用的变量不存在
1
console.log(a);
TypeError: 数据类型不正确
demo() 函数执行后返回的是一个空的 空的在调用就不行了
1
2const demo = ()=>{}
demo()()RangeError: 数据值不在其所允许的范围内 –死循环
1
const demo = ()=>{demo()}
**SyntaxError: 语法错误 **
2.2js错误的处理
try:中放可能存在错误的代码如果有错误进入 catch,catch有一个error的参数里放的是错误信息
1 | try{ |
throw 抛出错误
1 | function demo(){ |
- 错误对象的属性
- message :错误对象的相关信息
- stack:记录信息 错误出现在第几行等等
3.promise
简介:
**promise 翻译过来就是许诺 承诺的意思 **
作用是解决异步编程(以前是使用回纯回调函数实现的)
3.1 promise 的基本使用
** 1.Promise不是回调,是一个内置的构造函数,是程序员自己new调用的。**
2.new Promise的时候,要传入一个回调函数,它是同步的回调,会立即在主线程上执行,它被称为executor函数
3.每一个Promise实例都有3种状态:初始化(pending)、成功(fulfilled)、失败(rejected)
4.每一个Promise实例在刚被new出来的那一刻,状态都是初始化(pending)
5.executor函数会接收到2个参数,它们都是函数,分别用形参:resolve、reject接 收1.调用resolve函数会:
** (1).让Promise实例状态变为成功(fulfilled)
** (2).可以指定成功的value。
2.调用reject函数会:
** (1).让Promise实例状态变为失败(rejected)**
** ** (2).可以指定失败的reason。
1 | //创建一个Promise实例对象 |
1 |
|
3.2promise 结合ajax
1 | <script type="text/javascript"> |
简答的封装一个ajax
1 | <script type="text/javascript"> |
3.3promise 常用的api
- Promise构造函数: new Promise (executor) {}
** executor函数: 是同步执行的,(resolve, reject) => {}
** resolve函数: 调用resolve将Promise实例内部状态改为成功(fulfilled)。
** reject函数: 调用reject将Promise实例内部状态改为失败(rejected)。
** 说明: excutor函数会在Promise内部立即同步调用,异步代码放在excutor函数中。
- Promise.prototype.then方法:
** Promise实例.then(onFulfilled,onRejected)**
** onFulfilled: 成功的回调函数 (value) => {}**
** onRejected: 失败的回调函数 (reason) => {}
** 特别注意(难点):then方法会返回一个新的Promise实例对象- **Promise.prototype.catch方法: **
Promise实例.catch(onRejected)
onRejected: 失败的回调函数 (reason) => {}
说明: catch方法是then方法的语法糖, 相当于: then(undefined, onRejected)- Promise.resolve方法: Promise.resolve(value)
说明: 用于快速返回一个状态为fulfilled或rejected的Promise实例对象
备注:value的值可能是:(1)非Promise值 (2)Promise值
Promise.reject方法: Promise.reject方法(reason)
** 说明: 用于快速返回一个状态必为rejected的Promise实例对象**- Promise.resolve方法: Promise.resolve(value)
- Promise构造函数: new Promise (executor) {}
如果传入的值是数组 对象 数字这种 那么它生成的就是你指定的成功或者失败的promise
如果传入的是promise实例对象
**** Promise.reject方法(reason) 不管参数是成功的还是失败的返回的结果都是失败的 ****
1 | const p0 = Promise.resolve(100) |
- Promise.all方法: Promise.all(promiseArr)
promiseArr: 包含n个Promise实例的数组
说明: 返回一个新的Promise实例, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败。
只要数组里面有一个失败了就都失败了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const p1 = Promise.resolve('a')
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('b')
},500)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('c')
},2000)
})
const x = Promise.all([p1,p2,p3])
x.then(
value => {console.log('成功了',value);},
reason => {console.log('失败了',reason);}
)- Promise.all方法: Promise.all(promiseArr)
- Promise.race方法: Promise.race(promiseArr)
promiseArr: 包含n个Promise实例的数组
说明: 返回一个新的Promise实例, 成功还是很失败?以最先出结果的promise为准。
成功还是失败取决于谁最快的结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const p1 = Promise.reject('a')
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('b')
},500)
})
const p3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('c')
},2000)
})
const x = Promise.race([p3,p1,p2])
x.then(
value => {console.log('成功了',value);},
reason => {console.log('失败了',reason);}
)- Promise.race方法: Promise.race(promiseArr)
3.4 如何改变promise的状态
改变Promise实例的状态和指定回调函数谁先谁后?
1.都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
2.如何先改状态再指定回调? 延迟一会再调用then()
3.Promise实例什么时候才能得到数据?
** 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
** 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
3.5 then的链式调用
Promise实例.then()返回的是一个【新的Promise实例】,它的值和状态由什么决定?
** 1.简单表达: 由then()所指定的回调函数执行的结果决定
** 2.详细表达:
** (1)如果then所指定的回调返回的是非Promise值a:
** 那么【新Promise实例】状态为:成功(fulfilled), 成功的value为a
** (2)如果then所指定的回调返回的是一个Promise实例p:
** 那么【新Promise实例】的状态、值,都与p一致
** (3)如果then所指定的回调抛出异常:
** 那么【新Promise实例】状态为rejected, reason为抛出的那个异常
1 | <script> |
3.6中断promise链条
如果我们调用了很多then方法 ,但是我们想在第一次失败后就终止后面的调用,但是无论成功还是失败都会返回一个promise 实例,这个实例要么是成功的要么是失败的都会调用下一个then
解决方法:在失败的方法里面返回一个新的promise对象 这样它就是初始的值
value => {console.log(‘成功了1’,value); return Promise.reject(‘a’)},
** **reason => {console.log(‘失败了1’,reason),retunr new promise(()=>{})}
每一个是失败的方法里面都返回一个 new的promise实例
1 | value => {console.log('成功了1',value); return Promise.reject('a')}, |
3.7错误的穿透
**就是在链式调用的时候,如果某一个阶段出现了错误,我们就一直往后推,一直推到最后那个兜底的那个那里,这样就避免了没一个then后面的 **
4.async
- async修饰的函数
** 函数的返回值为promise对象
** Promise实例的结果由async函数执行的返回值决定- await表达式
** await右侧的表达式一般为Promise实例对象, 但也可以是其它的值
** (1).如果表达式是Promise实例对象, await后的返回值是promise成功的值
** **(2).如果表达式是其它值, 直接将此值作为await的返回值- 注意:
** await必须写在async函数中, 但async函数中可以没有await
** 如果await的Promise实例对象失败了, 就会抛出异常, 需要通过try…catch来捕获处理
1 | <script type="text/javascript"> |
小练习
1 | function sendAjax(url,data){ |
4.2 async 与啊await 使用
- async修饰的函数
** 函数的返回值为promise对象
** Promise实例的结果由async函数执行的返回值决定- await表达式
** await右侧的表达式一般为Promise实例对象, 但也可以是其它的值
** (1).如果表达式是Promise实例对象, await后的返回值是promise成功的值
** **(2).如果表达式是其它值, 直接将此值作为await的返回值- 注意:
** await必须写在async函数中, 但async函数中可以没有await
** 如果await的Promise实例对象失败了, 就会抛出异常, 需要通过try…catch来捕获处理
总结 被async修饰的函数 返回值值promise实例
await 要结合async使用 不然脑子就抽抽了 注意try catch的使用
4.3await 的原理
若我们使用async配合await这种写法:
** 1.表面上不出现任何的回调函数**
** 2.但实际上底层把我们写的代码进行了加工,把回调函数“还原”回来了。**
** 3.最终运行的代码是依然有回调的,只是程序员没有看见。**
1 | const p = new Promise((resolve,reject)=>{ |
4.4 宏队列与微队列
程序的执行都是有顺序的,在主线程上的是主线程是优先执行的,除此之外还有很多回回调,这些回到会被加入到队列中,但是队列有两种,一种是宏队列,一种是微队列,但是微队列的执行优先级要高于宏队列,当微队列里面的回调执行完了才会开始执行宏队列
宏队列:[宏任务1,宏任务2…..]
微队列:[微任务1,微任务2…..]
规则:每次要执行宏队列里的一个任务之前,先看微队列里是否有待执行的微任务
** 1.如果有,先执行微任务
** ** 2.如果没有,按照宏队列里任务的顺序,依次执行**
//当程序开始的时候。settimeout ,promise 的两个和console.log(主线程)都会瞬间执行完成 然后才会执行各自的回调,promise的回调是属于是微队列,settimeout的回调会加载到宏队列,promise的回调回加载到微队列
//所以程序的执行的结果是主线程 然后两个加载到微队列的promise回调 在然后是settimeout的回调
setTimeout(()=>{
console.log('timeout')
},0)
Promise.resolve(1).then(
value => console.log('成功1',value)
)
Promise.resolve(2).then(
value => console.log('成功2',value)
)
console.log('主线程')