Promise
-
对象: 皆对象
-
函数: 特定任务的代码块
-
构造函数 (被new的才是构造函数 不一定大写都是构造函数)
-
实例对象 (new 出来返回的对象) 简称对象
-
函数对象 (对象本身是函数 函数本来就是对象 任何皆对象)
改变this指向
-
call 第一个参数指向对象, 参数以
,
相隔 obj.myFun.call(db,'s', ... ,'string' ) -
apply 第一个参数指向对象, 参数以数组形式 obj.myFun.apply(db,['s', ..., 'string' ])
-
bind 返回的是一个回调函数 第一个参数指向对象obj.myFun.bind(db,'s', ... ,'string' )()
-
参数类型任意
-
第一个参数为null或undefined 指向window
回调函数
-
自己定义的但不是自己调的
-
函数A作为参数传递给函数B, 函数B执行函数A 那么A就是回调函数
-
回调函数没有名称 称为匿名回调函数
-
回调函数获取异步操作的结果
-
function fn(callBack){
setTimeout(()=>{
var data = "hello"
callBack(data)
},1000)
}
fn((data)=>{
console.log(data)//hello
})
同步回调
-
立刻执行, 完全执行完了才结束,不会放到回调队列中
-
Promise的excutor(执行器)数组遍历相关的回调函数forEach
-
const arr = [1, 2, 3]
arr.forEach(item =>{
console.log(item)
})
console.log("forEach回调之后")
// 1
// 2
// 3
// forEach回调之后
异步回调
-
不会立即执行, 会放入回调队列中将来执行
-
定时器回调/ajax回调/Promise的成功|失败的回调
-
setTimeout(()=>{
console.log("timeout")
},0)
console.log("setTimeout之后")
// setTimeout之后
// timeout
宏队列和微队列(先微后宏)
-
宏队列
dom事件对象回调
ajax回调
定时器回调
-
微队列
promise回调
mutation回调
-
微队列优先级高
-
先执行完同步 在微任务 在宏任务 宏任务执行前必须是没有微任务的
setTimeout(()=>{
console.log(1)
},0)
new Promise((resovle) => {
console.log(2)
resovle()
}).then(
()=>{
console.log(3)
}
).then(
()=>{
console.log(4)
}
)
console.log(5)
// 2 5 3 4 1
const first = () => (new Promise((resolve, reject) => {
console.log(3)
let p = new Promise((resolve, reject) => {
console.log(7)
setTimeout(()=>{
console.log(5)
resolve(6)//状态只改变一次
},0)
resolve(1)
})
resolve(2)
p.then((org) => {
console.log(org)
})
}))
first().then((org) => {
console.log(org)
})
console.log(4)
//3 7 4 1 2 5
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)
})
// 1 7 2 3 8 4 6 5 0
Error和错误处理
错误类型(常见的内置错误)
-
Error: 所有错误的父类型
-
ReferenceError: 引用的变量不存在
-
TypeError: 数据类型不正确的错误
-
RangeError: 数据值不在其所允许的范围内
-
SyntaxError: 语法错误
错误处理
-
捕获错误: try .... catch
-
抛出错误: throw error
错误对象
-
message属性: 错误相关信息
Cannot read property 'xxx' of undefined
-
stack属性: 函数调用栈记录信息
01.html:15 Uncaught TypeError: Cannot read property 'xxx' of undefined at 01.html:15
Promise
是什么
-
异步编程的新的解决方案 (旧的方案是纯回调)
-
语法上: 一个构造函数
-
功能上: promise对象用来封装一个异步操作并可以获取其结果
状态改变(3种 pending(初始) fulfilled rejected)
-
pending 通过resolve方法变为fulfilled
-
pending通过reject方法变为rejected
-
改变只有这两种,且pending对象只能改变一次
-
无论成功失败都有结果数据
-
成功为value
-
失败为reason
-
基本流程
new Promise(参数为函数)--->执行异步操作--->成功 执行resolve()-->变为fulfilled状态 pending状态 ----失败 执行reject() ---->变为rejected状态成功----->回调onFulfilled
then()
最后都返回新的Promise对象
失败---->回调onRejected
then()/catch()
基本使用
//1.创建promise对象 const p = new Promise((resolve, reject) => {//执行构造器 这里是同步的 console.log('执行构造器') //会先执行 //2. 执行异步操作 setTimeout(() => { const time = Date.now() //3.成功调用resolve(value) if (time % 2 == 0) { resolve('成功的数据, time=' + time) } else { //失败调用reject(reason) reject('失败的数据, time=' + time) } }, 1000)}) console.log('Promise之后') p.then( value => {//接收成功的value数据 onFulfilled console.log('成功的回调', value) }, reason => {//接收得到失败的reason数据 onRejected console.log('失败的回调', reason) } )</pre>
为什么用
-
旧的回调地狱: 回调嵌套回调 多个异步操作 上一次的结果是下一次的条件
-
不便于异常处理和阅读
-
Promise使用链式回调 async/await
-
-
指定回调函数更加灵活
-
旧的: 必须在启动异步任务之前指定
-
Promise: 启动异步任务==> 返回Promise对象===>给Promise对象绑定回调函数(甚至可以在异步中指定) 比如获取到数据需要2s,我3s后指定
-
一个Promise就是一个异步任务 返回的都是新的Promise
-
处理异常在最后处理 中间的任何一个错误都会在这里处理 异常传透
-
-
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) } }
如何使用API
-
语法糖 Promise.resolve()/Promise.reject()
-
Promise.all() 接收Promise数组对象 Promise.all([p1,p2,p3]) 支持不是promise的元素
-
成功返回的是结果数组对象,顺序对应
-
失败返回失败原因
-
-
Primise.race() 接收Promise数组对象 Promise.race([p1,p2,p3]) 支持不是promise的元素
-
成功或失败看最先执行完成的结果,最先的成功就成功
-
和顺序无关
-
关键问题
-
.then是同步的 当时 里面的回调函数(返回的结果回调)是异步的
-
如何改变Promise状态
1. resolve() 当前pendind ---> fullfilled
reject() 当前pendind ---> rejectedd
抛出异常 当前pendind ---> rejected
-
一个promise指定多个成功/失败回调函数,都会调用吗
当promise改变为对应状态时都会回调var p = new Promise((resolve,reject) => {
setTimeout(() => {
console.log('上课了')
resolve()
},10)
})
p.then(() => {
console.log('班长:起立')
})
p.then(() => {
console.log('同学们:老师好')
})//上课了 //班长:起立 //同学们:老师好 </pre>
-
改变promise状态和指定回调函数(then)谁先谁后
1. 都有可能, 正常情况下是先指定回调在改变状态, 但也可能相反 2. 如果先改变状态 1. 在执行器中直接调用resolve()/reject() 不进行异步 2. 延长更长时间才调用then 3. 什么时候才能得到数据 1.如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据 2.如果先改变状态, 那当执行回调时, 回调函数就会调用, 得到数据
-
链式回调的结果受上一次返回的Promise的影响
-
没有return 返回undefined
-
没有对应的回调函数 返回catch
-
相当于返回 reason => {throw reason}/reason => Promise.reject(reason)
-
-
-
promise.then()返回的新的pomise的结果状态有什么决定
简单表达: 由then()指定的回调函数执行的结果决定详细
如果抛出异常, 新的Promise变为rejected,reason为抛出的异常
如果返回的是非promise的任意值,新的promise变为fullfilled,value为返回的值
如果返回的是另一个新的Promise, 此Promise的结果做为新的结果
-
Promise如何串联多个操作任务
1. promise的then返回一个新的Promise,可以看成then()的链式调用 return new Promise() 新的里面处理异步 同步可以直接返回结果 不需要new Promise 因为Promise主要处理异步
- 通过then的链式调用串连多个同步/异步任务
-
promise异常传透
1. 当使用promise的then链式调用时, 可以在最后指定失败的回调2.前面任意操作出了异常, 都会传到最后失败的回调中处理
-
中断promise链
1. 当使用promise的then链式调用时, 在中间中断, 不在调用后面的回调函数2.办法: 在回调函数中返回一个pending状态的promise对象
return new Promise(()=>{})//返回一个pending状态的promise对象
自定义Promise
/* 整体结构 */(function (window) {
const PENDING = 'penging'
const FILLFULLED = 'fillfulled'
const REJECTED = 'rejected'/*
构造函数: excutor
执行器函数: excutor
*/function Promise(excutor) {
//存储当前this
const self = thisself.status = PENDING//初始状态 self.data = undefined//数据结果 self.callbacks = []//每个元素的结构 {onFillfulled(){}, onRejected() {}} function resolve(value) { //如果当前状态不是pending, 直接结束 保证状态只能变一次且只能从pending开始 if (self.status !== PENDING) { return } //改变状态 self.status = FILLFULLED //保存value数据 self.data = value //如果有待执行的callback函数, 立即异步执行回调函数 if (self.callbacks.length > 0) { setTimeout(() => {//放入队列中执行 self.callbacks.forEach(callbacksObj => { callbacksObj.onfullfilled(value) }) }) } } function reject(reason) { //如果当前状态不是pending, 直接结束 保证状态只能变一次且只能从pending开始 if (self.status !== PENDING) { return } //改变状态 self.status = REJECTED //保存value数据 self.data = reason //如果有待执行的callback函数, 立即异步执行回调函数 if (self.callbacks.length > 0) { setTimeout(() => {//放入队列中执行 异步执行 self.callbacks.forEach(callbacksObj => { callbacksObj.onRejected(reason) }) }) } } //立即执行 并且捕获异常 改变状态为reject try { excutor(resolve, reject) } catch (error) { reject(error) }
}
/*
Promise原型对象then和catch
*/Promise.prototype.then = function (onfullfilled, onRejected) {
onfullfilled = typeof onfullfilled === 'function' ? onfullfilled : value => value //向后传递
//指定迷人的失败的回调(实现错误/异常串透的关键)
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }const self = this //返回一个新的Promise return new Promise((resolve, reject) => { //回调函数封装 function handle(callback) { /* 1.抛出异常 失败 2.非promise 成功 3.是promise 看新的promise的结果 */ try { const result = callback(self.data) if (result instanceof Promise) { // result.then( // value => { // resolve(value) // }, // reason =>{ // reject(reason) // } // ) //--->简化 result.then(resolve, reject) } else { resolve(result) } } catch (error) { reject(error) } } //当前状态是pending 保存回调函数 if (self.status === PENDING) { self.callbacks.push({ onfullfilled(value) { handle(onfullfilled) }, onRejected(reason) { handle(onRejected) } }) } else if (self.status === FILLFULLED) {//如果是fillfulled状态 异步执行onFillfulled改变Promise状态 setTimeout(() => { handle(onfullfilled) }) } else {//如果是rejected状态 异步执行onReject改变Promise状态 setTimeout(() => { handle(onRejected) }) } })
}
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}/*
函数对象的resolve和reject方法
*/Promise.resolve = function (value) {
//返回一个成功/失败的Promise
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {//如果不是promise 直接成功
resolve(value)
}
})
}Promise.reject = function (reason) {
//返回一个失败的Promise
return new Promise((resolve, reject) => {
reject(reason)
})
}/*
函数对象的all和race方法
*/Promise.all = function (promises) {
const values = new Array(promises.length)//用来保存成功的value let fillfulled = 0 //保存promises的数量 return new Promise((resolve, reject) => { //遍历promise获取 promises.forEach((p, index) => { Promise.resolve(p).then(//包裹一层 包装为Promise value => {//成功存入数组 fillfulled++ values[index] = value //如果都成功 返回成功 if (fillfulled === promises.length) { resolve(values) } }, reason => {//只要有一个失败, 就失败 reject(reason) } ) }) })
}
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
//遍历promise获取
promises.forEach((p) => {
Promise.resolve(p).then(//包裹一层 包装为Promise
value => {//一旦成功就成功
resolve(value)
},
reason => {//一旦失败就失败
reject(reason)
}
)
})
})
}/*
返回一个promise对象, 他在指定的事件后才确定结果
*/
Promise.resolveDelay = function (value, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {//如果不是promise 直接成功
resolve(value)
}
}, time)
})
}Promise.rejectDelay = function (reason, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(reason)
}, time)
})
}//向外暴露函数
window.Promise = Promise
})(window)
class版本
/*
整体结构
*/
(function (window) {
const PENDING = 'penging'
const FILLFULLED = 'fillfulled'
const REJECTED = 'rejected'
class Promise {
/*
构造函数: excutor
执行器函数: excutor
*/
constructor(excutor) {
//存储当前this
const self = this
self.status = PENDING//初始状态
self.data = undefined//数据结果
self.callbacks = []//每个元素的结构 {onFillfulled(){}, onRejected() {}}
function resolve(value) {
//如果当前状态不是pending, 直接结束 保证状态只能变一次且只能从pending开始
if (self.status !== PENDING) {
return
}
//改变状态
self.status = FILLFULLED
//保存value数据
self.data = value
//如果有待执行的callback函数, 立即异步执行回调函数
if (self.callbacks.length > 0) {
setTimeout(() => {//放入队列中执行
self.callbacks.forEach(callbacksObj => {
callbacksObj.onfullfilled(value)
})
})
}
}
function reject(reason) {
//如果当前状态不是pending, 直接结束 保证状态只能变一次且只能从pending开始
if (self.status !== PENDING) {
return
}
//改变状态
self.status = REJECTED
//保存value数据
self.data = reason
//如果有待执行的callback函数, 立即异步执行回调函数
if (self.callbacks.length > 0) {
setTimeout(() => {//放入队列中执行 异步执行
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason)
})
})
}
}
//立即执行 并且捕获异常 改变状态为reject
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
/*
Promise原型对象then和catch
*/
then(onfullfilled, onRejected) {
onfullfilled = typeof onfullfilled === 'function' ? onfullfilled : value => value //向后传递
//指定迷人的失败的回调(实现错误/异常串透的关键)
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const self = this
//返回一个新的Promise
return new Promise((resolve, reject) => {
//回调函数封装
function handle(callback) {
/*
1.抛出异常 失败
2.非promise 成功
3.是promise 看新的promise的结果
*/
try {
const result = callback(self.data)
if (result instanceof Promise) {
// result.then(
// value => {
// resolve(value)
// },
// reason =>{
// reject(reason)
// }
// )
//--->简化
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
//当前状态是pending 保存回调函数
if (self.status === PENDING) {
self.callbacks.push({
onfullfilled(value) {
handle(onfullfilled)
},
onRejected(reason) {
handle(onRejected)
}
})
} else if (self.status === FILLFULLED) {//如果是fillfulled状态 异步执行onFillfulled改变Promise状态
setTimeout(() => {
handle(onfullfilled)
})
} else {//如果是rejected状态 异步执行onReject改变Promise状态
setTimeout(() => {
handle(onRejected)
})
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
/*
函数对象的resolve和reject方法
*/
static resolve = function (value) {
//返回一个成功/失败的Promise
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {//如果不是promise 直接成功
resolve(value)
}
})
}
static reject = function (reason) {
//返回一个失败的Promise
return new Promise((resolve, reject) => {
reject(reason)
})
}
/*
函数对象的all和race方法
*/
static all = function (promises) {
const values = new Array(promises.length)//用来保存成功的value
let fillfulled = 0 //保存promises的数量
return new Promise((resolve, reject) => {
//遍历promise获取
promises.forEach((p, index) => {
Promise.resolve(p).then(//包裹一层 包装为Promise
value => {//成功存入数组
fillfulled++
values[index] = value
//如果都成功 返回成功
if (fillfulled === promises.length) {
resolve(values)
}
},
reason => {//只要有一个失败, 就失败
reject(reason)
}
)
})
})
}
static race = function (promises) {
return new Promise((resolve, reject) => {
//遍历promise获取
promises.forEach((p) => {
Promise.resolve(p).then(//包裹一层 包装为Promise
value => {//一旦成功就成功
resolve(value)
},
reason => {//一旦失败就失败
reject(reason)
}
)
})
})
}
/*
返回一个promise对象, 他在指定的事件后才确定结果
*/
static resolveDelay = function (value, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {//如果不是promise 直接成功
resolve(value)
}
}, time)
})
}
static rejectDelay = function (reason, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(reason)
}, time)
})
}
}
//向外暴露函数
window.Promise = Promise
})(window)
async与await
-
async函数
-
函数
返回值为promise对象
-
promise结果由async函数执行的返回值决定
-
-
await表达式
-
表达式是promise对象或其他值
-
如果是promise, await返回的是promise成功的值
-
如果是其他值< 直接将此值作为await的返回值
-
-
注意
-
await必须写在async函数中, 但async中不一定有await
-
await的promise失败时,就会抛出异常,需要通过try..catch捕获
-