一
- 1.课程介绍
- 2.函数对象与实例对象
- 3.2种回调函数(同步与异步)
- 4.常见的内置错误
- 5.错误的处理(捕获与抛出)
- 6.Promise的理解
- 7.promise的状态和状态改变
- 8.Promise的基本运行流程
- 9.promise的基本使用
- 10.为什么要用Promise
- 11.Promise的API说明
- 12.Promise的API使用1
- 13.Promise的API使用2
课程介绍
函数对象与实例对象
- 实例对象: new 函数产生的对象, 称为实例对象, 简称为对象
- 函数对象: 将函数作为对象使用时, 简称为函数对
function Fn() { }
const fn = new Fn() // fn是实例对象
console.log(Fn.prototype)
Fn.bind({}) // Fn是 函数对象
$('#test') // $ 是函数
$.get('/test') // $ 是对象
补充:
()左边的是函数
. 左边的是对象
2种回调函数(同步与异步)
同步回调
- 理解: 立即执行, 完全执行完了才结束, 不会放入回调队列中
- 例子: 数组遍历相关的回调函数 / Promise 的 excutor 函数
异步回调
- 理解: 不会立即执行, 会放入回调队列中将来执行
- 例子: 定时器回调 / ajax 回调 / Promise 的成功|失败的回调
const arr = [1, 2, 3]
arr.forEach(item => console.log(item)) // 同步回调, 不会放入回调队列, 而是 立即执行
console.log('forEatch()之后')
setTimeout(() => { // 异步回调, 会放入回调队列, 所有同步执行完后才可能执行
console.log('timout 回调')
}, 0)
console.log('setTimeout 之后')
常见的内置错误
错误的类型
- Error: 所有错误的父类型
- ReferenceError: 引用的变量不存在
- TypeError: 数据类型不正确的错误
- RangeError: 数据值不在其所允许的范围内
- SyntaxError: 语法错误
错误处理
- 捕获错误: try … catc
- 抛出错误: throw error
error 对象的结构
- message 属性: 错误相关信息
- stack 属性: 函数调用栈记录信息
错误的处理(捕获与抛出)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JS的error处理</title>
</head>
<body>
<script>
/*
目标: 进一步理解JS中的错误(Error)和错误处理
mdn文档: https: //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error
1. 错误的类型
Error: 所有错误的父类型
ReferenceError: 引用的变量不存在
TypeError: 数据类型不正确的错误
RangeError: 数据值不在其所允许的范围内
SyntaxError: 语法错误
2. 错误处理
捕获错误: try ... catch
抛出错误: throw error
3. 错误对象
message属性: 错误相关信息
stack属性: 函数调用栈记录信息
*/
// 1. 常见的内置错误
// 1). ReferenceError: 引用的变量不存在
// console.log(a) // ReferenceError: a is not defined
// console.log('-----') // 没有捕获error, 下面的代码不会执行
// TypeError: 数据类型不正确的错误
// let b
// // console.log(b.xxx) // TypeError: Cannot read property 'xxx' of undefined
// b = {}
// b.xxx() // TypeError: b.xxx is not a function
// RangeError: 数据值不在其所允许的范围内
// function fn() {
// fn()
// }
// fn() // RangeError: Maximum call stack size exceeded
// SyntaxError: 语法错误
// const c = """" // SyntaxError: Unexpected string
// 2. 错误处理
// 捕获错误: try ... catch
// try {
// let d
// console.log(d.xxx)
// } catch (error) {
// console.log(error.message)
// console.log(error.stack)
// }
// console.log('出错之后')
// 抛出错误: throw error
function something() {
if (Date.now()%2===1) {
console.log('当前时间为奇数, 可以执行任务')
} else { // 如果时间是偶数抛出异常, 由调用来处理
throw new Error('当前时间为偶数无法执行任务')
}
}
// 捕获处理异常
try {
something()
} catch (error) {
alert(error.message)
}
</script>
</body>
</html>
Promise的理解
Promise 是什么?
理解
- 抽象表达: Promise 是 JS 中进行异步编程的新的解决方案(旧的是谁?)
- 具体表达:
(1) 从语法上来说: Promise 是一个构造函数
(2) 从功能上来说: promise 对象用来封装一个异步操作并可以获取其结果
promise的状态和状态改变
promise 的状态改变
- pending 变为 resolved
- pending 变为 rejected
说明: 只有这 2 种, 且一个 promise 对象只能改变一次
无论变为成功还是失败, 都会有一个结果数据
成功的结果数据一般称为 vlaue, 失败的结果数据一般称为 reason
Promise的基本运行流程
promise的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>04_promise基本使用</title>
</head>
<body>
<script>
// 1. 创建一个新的promise对象
const p = new Promise((resolve, reject) => {// 执行器函数 同步回调
console.log('执行 excutor')
// 2. 执行异步操作任务
setTimeout(() => {
const time = Date.now() // 如果当前时间是偶数就代表成功, 否则代表失败
// 3.1. 如果成功了, 调用resolve(value)
if (time %2 == 0) {
resolve('成功的数据, time=' + time)
} else {
// 3.2. 如果失败了, 调用reject(reason)
reject('失败的数据, time=' + time)
}
}, 1000);
})
console.log('new Promise()之后')
// setTimeout(() => {
p.then(
value => { // 接收得到成功的value数据 onResolved
console.log('成功的回调', value)
},
reason => {// 接收得到失败的reason数据 onRejected
console.log('失败的回调', reason)
}
// )
// }, 2000);
</script>
</body>
</html>
为什么要用Promise
指定回调函数的方式更加灵活
- 旧的: 必须在启动异步任务前指定
- promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函 数(甚至可以在异步任务结束后指定/多个)
支持链式调用, 可以解决回调地狱问题
- 什么是回调地狱?
回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件 - 回调地狱的缺点?
不便于阅读 不便于异常处理 - 解决方案?
promise 链式调用 ,单还有回调函数 - 终极解决方案?
async/await
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>05_为什么要用Promise</title>
</head>
<body>
<script>
/*
1. 指定回调函数的方式更加灵活:
旧的: 必须在启动异步任务前指定
promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定)
2. 支持链式调用, 可以解决回调地狱问题
什么是回调地狱? 回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调函数执行的条件
回调地狱的缺点? 不便于阅读 / 不便于异常处理
解决方案? promise链式调用
终极解决方案? async/await
*/
// 成功的回调函数
function successCallback(result) {
console.log("声音文件创建成功: " + result);
}
// 失败的回调函数
function failureCallback(error) {
console.log("声音文件创建失败: " + error);
}
/* 1.1 使用纯回调函数 */
createAudioFileAsync(audioSettings, successCallback, failureCallback)
/* 1.2. 使用Promise */
const promise = createAudioFileAsync(audioSettings); // 2
setTimeout(() => {
promise.then(successCallback, failureCallback);
}, 3000);
/*
2.1. 回调地狱
*/
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult)
}, failureCallback)
}, failureCallback)
}, failureCallback)
/*
2.2. 使用promise的链式调用解决回调地狱
*/
doSomething()
.then(function(result) {
return doSomethingElse(result)
})
.then(function(newResult) {
return doThirdThing(newResult)
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult)
})
.catch(failureCallback)
/*
2.3. 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)
}
}
</script>
</body>
</html>
Promise的API说明
Promise的API使用1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>06_Promise的API</title>
</head>
<body>
<script>
/*
1. Promise构造函数: Promise (excutor) {}
excutor函数: 同步执行 (resolve, reject) => {}
resolve函数: 内部定义成功时我们调用的函数 value => {}
reject函数: 内部定义失败时我们调用的函数 reason => {}
说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行
2. Promise.prototype.then方法: (onResolved, onRejected) => {}
onResolved函数: 成功的回调函数 (value) => {}
onRejected函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调
返回一个新的promise对象
3. Promise.prototype.catch方法: (onRejected) => {}
onRejected函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected)
4. Promise.resolve方法: (value) => {}
value: 成功的数据或promise对象
说明: 返回一个成功/失败的promise对象
5. Promise.reject方法: (reason) => {}
reason: 失败的原因
说明: 返回一个失败的promise对象
6. Promise.all方法: (promises) => {}
promises: 包含n个promise的数组
说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败
7. Promise.race方法: (promises) => {}
promises: 包含n个promise的数组
说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态
*/
new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('成功的数据')
reject('失败的数据')
}, 1000)
}).then(
value => {
console.log('onResolved()1', value)
}
).catch(
reason => {
console.log('onRejected()1', reason)
}
)
// 产生一个成功值为1的promise对象
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 100);
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
// p1.then(value => {console.log(value)})
// p2.then(value => {console.log(value)})
// p3.catch(reason => {console.log(reason)})
// const pAll = Promise.all([p1, p2, p3])
const pAll = Promise.all([p1, p2])
/* pAll.then(
values => {
console.log('all onResolved()', values)
},
reason => {
console.log('all onRejected()', reason)
}
)
*/
const pRace = Promise.race([p1, p2, p3])
pRace.then(
value => {
console.log('race onResolved()', value)
},
reason => {
console.log('race onRejected()', reason)
}
)
</script>
</body>
</html>