★ 概述
js是单线程,为什么是单线程,最早javascript设计的语言就是运行再浏览器端的脚本语言,实现页面动态交互,核心就是DOM操作,所以必须使用单线程模型,
js执行环境中,负责执行代码的线程只有一个
主要内容如下
同步与异步
时间循环与消息队列
异步编程几种方式
Promise异步方案、宏任务、微任务队列
Generator异步方案、es2017async await语法糖
★同步
在调用栈中压入匿名调用,把全部代码放到匿名函数中执行,只有调用的时候才会压入调用栈,声明的时候不会入栈
★异步
不会等待这个任务结束才开始下一个任务
消息队列和事件循环实现的,
call stask 调用栈是一个真正执行的工作表
queue消息队列就是一个代办的工作表
js引擎先去执行调用栈中的任务,然后通过事件循环evenloop,去消息队列中再取一个任务出来,放到调用栈中,依次去执行,以此类推,随时网消息队列queue中放入任务,会排队等待eventloop时间循环,
web apis 就是像settimeout这种,计时器,倒计时,就在这里执行,倒计时结束了,就把任务放到queue任务队列里
虽然js是单线程的,但是浏览器不是单线程的,像settimeout哪些就是用的浏览器的其他线程去执行的,我们说的单线程也只是执行自己js代码的线程是单线程的,
★ 回调函数
★ promise
概述
承诺,一开始是待定的状态是pending,后面变成成功fulfilled或者失败rejected
链式调用
不要嵌套使用,要链式调用
Promise对象的then会返回一个全新的Promise对象,所以可以使用链式调用的方式进行调用
异常处理
catch是then的别名 相当于then(undefined, onRejected),用catch更适用链式调用
// 使用第二个参数失败回调函数
ajax('/api/users11.json')
.then(function onFulfilled (value) {
console.log('onFulfilled', value)
}, function onRejected (error) {
console.log('onRejected', error)
})
// 使用catch
ajax('/api/users11.json')
.then(function onFulfilled (value) {
console.log('onFulfilled', value)
})
.catch(function onRejected (error) {
console.log('onRejected', error)
})
// then(onRejected) 实际上就相当于 then(undefined, onRejected)
ajax('/api/users11.json')
.then(function onFulfilled (value) {
console.log('onFulfilled', value)
})
.then(undefined, function onRejected (error) {
console.log('onRejected', error)
})
全局异常捕获
不建议全局捕获异常,有什么问题就在当前逻辑下面捕获异常处理
window.addEventListener('unhandledrejection', event => {
const { reason, promise } = event
console.log(reason, promise)
// reason => Promise 失败原因,一般是一个错误对象
// promise => 出现异常的 Promise 对象
event.preventDefault()
}, false)
// Node.js 中使用以下方式
process.on('unhandledRejection', (reason, promise) => {
console.log(reason, promise)
// reason => Promise 失败原因,一般是一个错误对象
// promise => 出现异常的 Promise 对象
})
静态方法
Promise.resolve('foo')
.then(function (value) {
console.log(value)
})
Promise.reject('anything')
.catch(function (error) {
console.log(error)
})
// thenable接口了解
// 如果传入的是带有一个跟 Promise 一样的 then 方法的对象,
// Promise.resolve 会将这个对象作为 Promise 执行
Promise.resolve({
then: function (onFulfilled, onRejected) {
onFulfilled('foo')
}
})
.then(function (value) {
console.log(value)
})
并行执行
- all 等待所有任务结束才算结束
- race 等待第一个结束的任务,结果以第一个promise返回结果为准,就是最快的一个promise的返回
promise执行顺序
promise是微任务,直接在当前任务结束过后,立即去执行,不会再回调队列的末尾,而是插队,不用重新排队,提高了整体的相应能力,
settimeout是宏任务的形式进入到回调队列的末尾,大部分都是宏任务,
Promise 、MutationObserver、Process.nextTick 是微任务
★ Generator es2015
调用、执行、异常
调用:执行带*号的函数,得到的是生成器对象,只有手动调用next()方法,这个函数的函数体才会开始执行
执行:调用next传入的参数,会作为yeild执行的返回值
异常:generator.throw() 带*的函数里面执行异常使用try catch捕获
done 属性为true,生成器结束
// 生成器函数回顾
function * foo () {
console.log('start')
try {
const res = yield 'foo'
console.log(res)
} catch (e) {
console.log(e)
}
}
const generator = foo()
const result = generator.next()
console.log(result)
// generator.next('bar')
generator.throw(new Error('Generator error'))
// 输出结果
start
{ value: 'foo', done: false }
Error: Generator error
生成器函数执行器co
★ async await
- 带*函数改成 async yield改成await
- async 函数返回一个Promise对象
- await 必须再async函数内部使用
★ Promise 类核心逻辑实现
1. Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
2. Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending
pending -> fulfilled
pending -> rejected
一旦状态确定就不可更改
3. resolve和reject函数是用来更改状态的
resolve: fulfilled
reject: rejected
4. then方法内部做的事情就判断状态 如果状态是成功 调用成功的回调函数
如果状态是失败 调用失败回调函数 then方法是被定义在原型对象中的
5. then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
6. 同一个promise对象下面的then方法是可以被调用多次的
7. then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
new promise ()
()里面传递一个函数,这个函数就是执行器
class promise
class promise 里面通过constructor把执行器接收到,然后调用执行器,就是constructor的参数,执行,立即执行
异步处理
异步处理,添加成功失败的回调函数
多个then方法
多个then方法,就把回调函数初始设置成 数组[ ],使用的时候用push或者shift
链式调用 then的值取决于上一个回调函数的返回值
- 1.返回一个Promise对象。
- 2.then的返回值传递给下一个回调函数