Promise的理解与使用
1.理解所要掌握的基础:
首先我们来了解一下在js中什么是同步什么异步:
1.1 同步
因为JS是单线程的,所有的任务都是在主线程上排队执行。
HTML5 新增web worker 允许js创建多线程,完全受到主线程控制的,但是不能修改DOM
1.2 异步
页面渲染的时候有一些耗时的操作,可以丢到主线程,不影响主线程继续执行
1.3. Event Loop(重点\难点)
所有的同步代码在执行的时候 异步代码不进入主线程,而是在event table中注册函数,当满足条件后,然后进入(任务队列)中,通知主线程我可以执行了,如果主线程没有同步任务了,那就可以执行了.
1.4 执行栈
存储函数调用的栈结构,同步任务都是在主线程执行, 形成一个执行栈.
1.5 任务队列
主线程之外 遇到异步代码会挂起,将注册的回调函数加入[任务队列]
1.6 任务队列分类
宏任务(MacroTask)
script 整体、setTimeout、setInterval、setTimediate、I/O
UI Rendering
微任务(MicroTask)
Promise 的 then、 process、nextTick.
MutationObserve等
重点:Event Loop执行顺序(浏览器端):
- 首先执行script下面的宏任务;
- 遇到同步代码直接执行,遇到setTimeout等 丢到宏任务队列,遇到then丢到微任务队列
- 执行完毕后,清空 执行栈;
- 然后从微任务中取出第一个任务执行,然后继续取出微任务队列中的任务执行,直到全部执行完毕;
- 如果在执行微任务的时候,又产生了新的微任务,也会在当前周期被调用执行(加在微任务队列后面排队);
- 所有微任务执行完毕后,会执行第一个宏任务
- 不会继续执行宏任务,而是检查微任务队列是否有新任务,有则执行;
- 接着当前宏任务的第一个,然后继续检查微任务,依次类推
- 注意: 微任务每次都是全部执行,而宏任务每次只执行第一个.
2.Promise(重点.难点)
2.1概念
抽象表达:
1) Promise 是一门新的技术(ES6 规范)
2)Promise 是 JS 中进行异步编程的新解决方案 备注:旧方案是单纯使用回调函数是用于
从语法上讲,是一个对象;
从本意上讲,就是一个承若,言出必行、不可反悔。
promise的基本流程:
三种状态:
- Peding – promise对象创建的时候初始状态;
- Fulfilled-- 成功状态
- Rejected – 失败的状态
注意:一旦Peding转为Fulfilled,就不能再改了,
同样的Peding转为Rejected,也不能在改变了
能解决问题:
回调地狱
支持并发请求
语法:
new Promise(function(resolve, reject){
//固定写法
//但是只能选择resolve或者reject执行resolve()
reject(1)
})
.then(function(res){
//res就是promise中resolve传递的值
})
.catch(function(err){
// err 就是 promise中reject传递的值
})
举例:
var p = new Promise(function(resolve,reject){
setTimeout(function(){
let num = Math.ceil(Math.random()*10)//返回1-10的随机数
if(num > 5 ){
resolve(num)
}else{
reject('数字小了'+num)
}
},2000)
})
p.then(
function (res){
console.log("调用 resolve 的时候会执行:",res)
},
function(err){
console.log('调用reject的时候执行',err)
}
)
//两种方法都可以用下面的更加简便
p.then(function(res){
console.log("调用resolve 的时候会执行",res)
}).catch(function (err) {
console.log("调用 reject 的时候执行:", err)
})
//合并在一起
p.then((res,err) =>{
console.log("调用resolve 的时候会执行",res)
console.log("调用 reject 的时候执行:", err)
})
- resolve 函数:将promise的状态转为成功状态,在异步操作成功的时候调用,并把操作结果作为参数传递出去
- reject函数;将promise的状态变为失败状态,在异步操作失败的时候调用,并把操作结果作为参数传递出去
- Promise.prototype.then()
- 接收两个参数,第一个参数是resolve的回调;第二个参数是reject的回调;
- Promise.prototype.catch()
- reject的回调,作用与then的第二个参数相同.
- 不同的是可以捕获前面所以的promise的错误.
promise链式写法
p
.then()
.then()
.then()
//…
.catch()
Promis.resolve()
直接返回成功.
等价于: new Promise(resolve => resolve() )
Promise.reject()
失败.
等价于: new Promise(reject => reject() )
Promise.all()
接受一个数组参数,数组的元素是promise,会等到所有的promise成功后再成功,如果有一个失败则会全部失败。
既 比谁跑的慢.
Promise.race()
接受一个数组作为参数,数组的元素是promise,跑的最快的成功 不管失败
2.2 async/await(ES7)
理解 用于异步转同步
async function 函数名() {
await Promise
}
执行到 await 时,await 会阻塞后面的代码,必须等到 await 右边的代码拿到结果。
举例错误捕获
try {
// 要执行的代码块
} catch(err) {
// 错误处理
}
举例
```javascript
// 读取文件
const {rejects} = require("assert")
const fs = require("fs")
const t1 = read("./t1.txt")
const t2 = read("./t2.txt")
// 依次输出 t1 和 t2 的内容
async function run() {
try {
let t1 = await read("./t1.txt")
console.log("t1:", t1)
let t2 = await read("./t2.tt")
console.log("t2:", t2)
} catch (err) {
console.log("捕获错误:", err)
}
}
run()