前面我们学习了生成器和迭代器,那么在本篇文章中,我们主要讲解生成器与Promise的结合使用,从而引出async/await语法,同时会涉及面试中频次最高的一个知识点:事件循环
//伪代码 function request(url) { //请求的逻辑代码 //返回一个结果 return res; } //这样一层嵌套着一层,就是回调地狱 request("第一次").then((res1) => { request("第二次" + res1).then((res2) => { request("第三次" + res2); }); });
function request(url) { return new Promise((resolve, reject) => { resolve(url); }); } //这样就解决了回调地狱的问题,将代码写成了链式调用 request("第一次") .then((res1) => { console.log(res1); return request("第二次" + res1); }) .then((res2) => { console.log(res2); return request("第三次" + res2); }) .then((res3) => { console.log(res3); return request("结束"); });
/*理想代码 function getData(){ let res = yield request(url); let res1 = yield request(res); let res2 = request(res1); } */ function request(url) { return new Promise((resolve, reject) => { resolve(url); }); } //在获取上一次结果之后,再进行下一次请求 //因此我们就可以应用到yield function* getdata(url) { //yield空格后面的函数会直接执行 let res = yield request(url); let res1 = yield request(res); let res2 = yield request(res1); console.log("请求结束"); } //执行生成器函数 let generator = getdata("test"); //这时候执行next,其返回值{value:Promise,done{false}} //因此我们获取value调用then方法,就可以获取resolve的值 // console.log(generator.next()); generator.next().value.then((res) => { console.log(res); //第一次执行完之后,就会去进行下一次请求 generator.next(res + "test").value.then((res1) => { console.log(res1); //第二次执行完之后,就会进行第三次 generator.next(res1 + "test").value.then((res2) => { console.log(res2); //此时运行最后一行console代码 generator.next(); }); }); });
function request(url) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(url); }, 2000); }); } //在获取上一次结果之后,再进行下一次请求 //因此我们就可以应用到yield async function getdata(url) { //yield空格后面的函数会直接执行 let res = await request(url + 1); console.log(res); let res1 = await request(res + 2); console.log(res1); let res2 = await request(res1 + 3); console.log(res2); console.log("请求结束"); } getdata("test");
函数分为:普通函数、生成器函数、异步函数,本次就开始学习异步函数
async function foo(){} const bar = async ()=>{}
异步函数内部代码执行过程和普通函数是一致的
//其他情况之前的文章有讲过,不再演示 async function foo() { return 123; } foo().then((res) => { console.log(res);//123 });
异步函数返回的是一个Promise,Promise有三种状态,正常执行是pending,return是fulfilled,那么何时抛出异常
async function foo() { //在执行的时候,不会立即报错,会将错误信息用reject包裹 "123".filter(); //或者使用throw进行抛出异常 throw new Error("主动抛出异常") return 123; } foo() .then((res) => { console.log(res); //123 }) .catch((err) => { console.log(err); //不会影响下面的代码执行 console.log(123456); });
function request(count) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(count); }, 1000); }); } async function getData() { let res = await request(1); console.log(res); let res1 = await request(res + 1); console.log(res1); let res2 = await request(res1 + 1); console.log(res2); } getData();
function request(count) { return new Promise((resolve, reject) => { setTimeout(() => { reject(count); }, 1000); }); } //方式一 async function getData() { let res = await request(1); console.log(res); let res1 = await request(res + 1); console.log(res1); let res2 = await request(res1 + 1); console.log(res2); } //因为异步函数的返回值是Promise getData().catch((err)=>{ console.log(err) }) //方式二,使用try catch async function getData() { try { let res = await request(1); console.log(res); let res1 = await request(res + 1); console.log(res1); let res2 = await request(res1 + 1); console.log(res2); } catch (error) { console.log(error); } }
async function first(){} async function second(){} async function third(){} async function foo(){ //第一个函数执行完成,且返回的是fulfilled状态,才会执行下面的代码 await first() await second() await third() } foo()
JS是单线程(可以开启workers),但是JS的线程有自己的 容器:浏览器和Node
浏览器是多进程的,当我们打开 一个新的tab页面的时候,就会开启一个新的进程,这是为了防止一个页面卡死,而造成所有页面无法响应
每个进程会有多个线程,其中有一个线程是专门分给JS代码运行的
即,JS代码一次只能做一次事情,如果这个线程十分耗时,当前线程 就会阻塞
所以真正耗时的操作,并不是由JS线程在执行的
事件循环中并非只维护者一个队列,事实上有两个队列:宏任务队列和微任务队列
宏任务队列:ajax、setTimeout、setInterval、DOM监听、Rendering等
**微任务队列:**Promise的then回调(Promise中的代码会立即执行),Mutation Observer API queueMicrotask()等
那么这两个队列的优先级是什么样的
遇到throw,代码就会停止执行,且后面的代码不会执行
throw {message:"错误",code:-1001}
throw new Error("这是错误") //会把错误地方的调用栈,错误信息都会打印出来
当代码抛出异常之后,不去捕获的话,就会很危险
try catch捕获异常
function bar(){ throw "我是错误" } function foo(){ try{ foo() }catcha(error){ console.log(error) } } foo()