文章目录
- 1. 预备知识
- 2. Promise的理解和使用
-
- 2.1 Promise是什么
- 2.2 为什么要用 Promise
- 2.3 如何使用 Promise
-
- 1. Promise 构造函数:`Promise(executor) {}`
- 2. Promise.prototype.then 方法:`p.then(onResolved, onRejected)`
- 3. Promise.prototype.catch 方法:`p.catch(onRejected)`
- 4. Promise.resolve 方法:`Promise.resolve(value)`
- 5. Promise.reject 方法:`Promise.resolve(reason)`
- 6. Promise.all 方法:`Promise.all(iterable)`
- 7. Promise.race方法:`Promise.race(iterable)`
- 3. Promise 的几个关键问题
- 参考
1. 预备知识
1.1 实例对象与函数对象
- 实例对象:new 函数产生的对象,称为实例对象,简称为对象
- 函数对象:将函数作为对象使用时,称为函数对象
function Fn() {
// Fn只能称为函数
}
const fn = new Fn() // Fn只有new过的才可以称为构造函数
//fn称为实例对象
console.log(Fn.prototype)// Fn作为对象使用时,才可以称为函数对象
Fn.bind({
}) //Fn作为函数对象使用
$('#test') // $作为函数使用
$.get('/test') // $作为函数对象使用
()左边是函数,点左边是对象(函数对象、实例对象)
1.2 两种类型的回调函数
1. 同步回调
立即执行,完全执行完了才结束,不会放入回调队列中
数组遍历相关的回调 / Promise的executor函数
const arr = [1, 3, 5];
arr.forEach(item => {
// 遍历回调,同步回调,不会放入队列,一上来就要执行
console.log(item);
})
console.log('forEach()之后')
2. 异步回调
不会立即执行,会放入回调队列中将来执行
定时器回调 / ajax回调 / Promise成功或失败的回调
// 定时器回调
setTimeout(() => {
// 异步回调,会放入队列中将来执行
console.log('timeout callback()')
}, 0)
console.log('setTimeout()之后')
// Promise 成功或失败的回调
new Promise((resolve, reject) => {
resolve(1)
}).then(
value => {
console.log('value', value)},
reason => {
console.log('reason', reason)}
)
console.log('----')
// ----
// value 1
js 引擎先把初始化的同步代码都执行完成后,才执行回调队列中的代码
1.3 JS中的异常error处理
1. 错误的类型
Error
:所有错误的父类型
ReferenceError
:引用的变量不存在
console.log(a) // ReferenceError:a is not defined
TypeError
:数据类型不正确
let b
console.log(b.xxx)
// TypeError:Cannot read property 'xxx' of undefined
let c = {
}
c.xxx()
// TypeError:c.xxx is not a function
RangeError
:数据值不在其所允许的范围内
function fn() {
fn()
}
fn()
// RangeError:Maximum call stack size exceeded
SyntaxError
:语法错误
const c = """"
// SyntaxError:Unexpected string
2. 错误处理(捕获与抛出)
抛出错误:throw error
function something() {
if (Date.now()%2===1) {
console.log('当前时间为奇数,可以执行任务')
} else {
//如果时间为偶数抛出异常,由调用来处理
throw new Error('当前时间为偶数,无法执行任务')
}
}
捕获错误:try ... catch
// 捕获处理异常
try {
something()
} catch (error) {
alert(error.message)
}
3. 错误对象
- massage 属性:错误相关信息
- stack 属性:函数调用栈记录信息
try {
let d
console.log(d.xxx)
} catch (error) {
console.log(error.message)
console.log(error.stack)
}
console.log('出错之后')
// Cannot read property 'xxx' of undefined
// TypeError:Cannot read property 'xxx' of undefined
// 出错之后
因为错误被捕获处理了,后面的代码才能运行下去,打印出‘出错之后’
2. Promise的理解和使用
2.1 Promise是什么
1. 理解Promise
-
抽象表达:
Promise
是JS中进行异步编程的新的解决方案(旧方案是单纯使用回调函数)
【推荐阅读 【JavaScript】同步与异步-异步与并行-异步运行机制-为什么要异步编程-异步与回调-回调地狱-JavaScript中的异步操作】
---- 异步编程 ①fs 文件操作 ②数据库操作 ③Ajax ④定时器 -
具体表达:
①从语法上看:Promise
是一个构造函数 (自己身上有all
、reject
、resolve
这几个方法,原型上有then
、catch
等方法)
②从功能上看:promise
对象用来封装一个异步操作并可以获取其成功/失败的结果值 -
阮一峰的解释:
所谓Promise
,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果
从语法上说,Promise
是一个对象,从它可以获取异步操作的消息
Promise
提供统一的 API,各种异步操作都可以用同样的方法进行处理
2. Promise 的状态
实例对象promise中的一个属性 PromiseState
pending
变为resolved
/fullfilled
pending
变为rejected
注意
- 对象的状态不受外界影响
- 只有这两种,且一个
promise
对象只能改变一次 - 一旦状态改变,就不会再变,任何时候都可以得到这个结果
- 无论成功还是失败,都会有一个结果数据。成功的结果数据一般称为
value
,而失败的一般称为reason
。
3. Promise对象的值
实例对象promise的另一个值 PromiseResult
保存着对象 成功/失败 的值(value
/reason
)
resolve
/reject
可以修改值
4. Promise 的基本流程
5. Promise 的基本使用
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(reason);
}
});
Promise
构造函数接受一个函数(执行器函数)作为参数,该函数的两个参数分别是resolve
和reject
。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve
函数的作用是,将Promise
对象的状态从“未完成”变为“成功”(即从 pending
变为 resolved
),在异步操作成功时调用,并将异步操作的结果,作为参数value
传递出去;
reject
函数的作用是,将Promise
对象的状态从“未完成”变为“失败”(即从 pending
变为 rejected
),在异步操作失败时调用,并将异步操作报出的错误,作为参数error
/reason
传递出去。
Promise
实例生成以后,可以用then
方法分别指定resolved
状态和rejected
状态的回调函数。
promise.then(function(value) {
// success
}, function(reason) {
// failure
});
then
方法可以接受两个回调函数作为参数。
第一个回调函数onResolved()
是Promise
对象的状态变为resolved
时调用
第二个回调函数onRejected()
是Promise
对象的状态变为rejected
时调用
这两个函数都是可选的,不一定要提供。它们都接受Promise
对象传出的值作为参数
- 一个例子
// 创建一个新的p对象promise
const p = new Promise((resolve, reject) => {
// 执行器函数
// 执行异步操作任务
setTimeout(() => {
const time = Date.now()
// 如果当前时间是偶数代表成功,否则失败
if (time % 2 == 0) {
// 如果成功,调用resolve(value)
resolve('成功的数据,time=' + time)
} else {
// 如果失败,调用reject(reason)
reject('失败的数据,time=' + time)
}
}, 1000);
})
p.then(
value => {
// 接收得到成功的value数据 onResolved
console.log('成功的回调', value) // 成功的回调 成功的数据,time=1615015043258
},
reason => {
// 接收得到失败的reason数据 onRejected
console.log('失败的回调', reason) // 失败的回调 失败的数据,time=1615014995315
}
)
.then() 和执行器(executor)同步执行,.then() 中的回调函数异步执行
2.2 为什么要用 Promise
1.指定回调函数的方式更加灵活
旧的:必须在启动异步任务前指定
// 1. 纯回调的形式
// 成功的回调函数
function successCallback(result) {
console.