ES6新增API语法
ES6新增语法
新增异步处理的操作
-
异步的理解
- 宿主环境:浏览器环境/Node环境
- 我们写了一段JS代码时,浏览器或Node环境传递给JS引擎,并且要求他们去执行,所以JS引擎会常驻在内存中,等待宿主环境(我们)把JS代码传递给他去执行
- ES3及其之前JS本身没有能力执行异步代码,宿主环境将代码传递给JS引擎,JS引擎就顺次执行下去,这个任务是宿主发起的
- ES5之后,JS引入了Promise,不需要宿主环境安排,JS引擎本身也就可以发起任务
- 宿主发起的任务称之为:宏任务
- JS引擎发起的任务称之为:微任务
- 理解:JS语言本身是没有异步处理的能力,是宿主环境(浏览器,nodeJS)处理了异步的操作
-
事件循环:
- JS引擎等待宿主环境分配宏任务,在操作系统中,等待的行为都是一个事件循环,所以在Node术语这一部分称之为:事件循环
Promise
const promise = new Promise(
(resolve,reject)=>{
resolve('你好promise')
}
)
promise.then((res)=>{console.log(res)}); //'你好promise
'
- 是一个构造函数,需要通过new Promise调用,返还一个Promise对象
- 构造函数Promise((resolve,reject)={})有一个参数
- 调用resolve(res);则返回一个成功的Promise对象
- 调用reject(res);则返回一个失败的Promise对象
- 构造函数Promise((resolve,reject)={})有一个参数
- 返回的Promise对象有.then(resolver,rejector)方法,
- resolver(res) res为new Promise((resolve)=>{resolve(res)})
- rejector(res) res为new Promise((resolve,reject)=>{reject(res)})
- 特征:
- new Promise(()={//同步代码})
- .then(()=>{//异步代码,微任务},()=>{})
generator
function* foo(){
yield 'hello';
yield 'world';
return 'ending';
}
let t = foo();
t.next(); //{value: 'hello', done: false}
t.next(); //{value: 'world', done: false}
t.next(); //{value: 'ending', done: true}
t.next(); //{value: 'undefined', done: true}
generator函数知识点:
- generator函数是一个状态机。
- 调用generator函数只返回遍历器对象(Interator Object),不返回结果
- 返回的遍历器对象调用next方法,开始执行yield 后面的表达式,返回{value: ‘hello’, done: false};直到遇到下一个yield或return停止执行。
- 第二次调用t.next(),从上一次停下来的地方开始执行下一个yield后的表达式’world’,返回yield后表达式的结果{value: ‘world’, done: false};以此类推
- generator函数是分段执行的,函数是可以暂停执行的函数 (遇到yield就暂停执行);next恢复执行
function* foo(x) {
let y = 2 * (yield (x + 1));
let z = yield (y / 3);
return (x + y + z);
};
let it = foo(5);
console.log('it', it);
console.log(it.next()); //{value: 6, done: false}
console.log(it.next(12));
console.log(it.next(13));
generator函数数据交换:
异步的终极解决方案async await
- 就是generator加上Promise的语法糖
- 封装了generator的执行器和返回一个Promise
- 返回的是一个Promise
- await后面【表达式】的可以是一个Promise也可以是一个值,但是最终都转换成resolved的Promise;
- await 下面的代码相当于Promise的then里的代码
- 区别generator:内置了执行器,而且语义上更好理解,将异步函数以普通同步函数的方式书写。generator需要next函数触发执行
function sleep (sec) {
return new Promise((resolve,reject)=>{setTimeout(resolve,sec)})
};
sleep(2000).then(()=>{console.log('hello')})
async sleep (sec) {
console.log('hello');
await sleep(3000);
console.log('world');
}
async function async1() {
console.log('async1 start')
await async2() //等async2执行完毕,会阻塞后面的代码,跳出async函数,执行其他代码
console.log('async1 end') //放入到Promise.then中的代码
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1();
new Promise(function (resolve) {
console.log('promise1')
resolve();
}).then(function () {
console.log('promise2')
})
console.log('script end')
/*
同:‘script start’ ‘async1 start’ ‘async2’ promise1 ‘script end’
宏:‘setTimeout’
微:‘async1 end’ ‘promise2’
*/
实操案例
//实现一个红绿灯,把一个圆形div按照绿色3秒,黄色1秒,红色2秒循环改变背景色
<style>
#test {
border: 20px;
width: 100px;
height: 100px;
background-color: #ccc;
border-radius: 50%;
}
</style>
<body>
<div id="test"></div>
<script>
const light = document.getElementById( 'test' );
console.log( light );
function sleep( sec ) {
return new Promise( ( resolve, reject ) => {
setTimeout( resolve, sec );
} )
};
async function shineLight() {
while ( 1 )
{
light.style.backgroundColor = 'green';
await sleep( 3000 );
light.style.backgroundColor = 'yellow';
await sleep( 1000 );
light.style.backgroundColor = 'red';
await sleep( 2000 );
}
}
shineLight();
</script>
</body>