目录
首先来看个需求 :
向服务器发送网络请求获取数据,一共需要发送三次请求
- // 模拟发送请求,真实情况肯定是不同的请求,这里只使用这一个,道理一样
- function requestHttp(url) {
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve(url);
- }, 2000);
- });
- }
- // 第一次请求
- requestHttp('http://').then((res1) => {
- console.log('res1', res1); // res1 http://
- // 第二次请求
- requestHttp(res1 + 'www').then((res2) => {
- console.log('res2', res2); // res2 http://www
- // 第三次请求
- requestHttp(res2 + '.baidu.').then((res3) => {
- console.log('res3', res3); // res3 http://www.baidu.
- // 第四次请求
- requestHttp(res3 + 'com').then((res4) => {
- console.log('res4', res4); // res4 http://www.baidu.com
- });
- });
- });
- });
- // 第一次请求
- requestHttp('http://')
- .then((res1) => {
- console.log('res1', res1); // res1 http://
-
- // 第二次请求
- return requestHttp(res1 + 'www');
- })
- .then((res2) => {
- console.log('res2', res2); // res2 http://www
-
- // 第三次请求
- return requestHttp(res2 + '.baidu.');
- })
- .then((res3) => {
- console.log('res3', res3); // res3 http://www.baidu.
-
- // 第四次请求
- return requestHttp(res3 + 'com');
- })
- .then((res4) => {
- console.log('res4', res4); // res4 http://www.baidu.com
- });
- // 1. 定义生成器函数
- function* excuteCode() {
- const res1 = yield requestHttp('http://');
- console.log('res1', res1); // res1 http://
-
- const res2 = yield requestHttp(res1 + 'www');
- console.log('res2', res2); // res2 http://www
-
- const res3 = yield requestHttp(res2 + '.baidu.');
- console.log('res3', res3); // res3 http://www.baidu.
-
- const res4 = yield requestHttp(res3 + 'com');
- console.log('res4', res4); // res4 http://www.baidu.com
- }
-
- // 2. 拿到生成器对象
- const excuteIterator = excuteCode();
-
- // 3. 执行,把第一个请求的promise返回了出来,是promise
- excuteIterator.next().value.then((res1) => {
- // 4. 调用next()继续执行,同时把第一个请求的结果传入,把第二个请求的promise返回了出来
- excuteIterator.next(res1).value.then((res2) => {
- excuteIterator.next(res2).value.then((res3) => {
- excuteIterator.next(res3).value.then((res4) => {
- excuteIterator.next(res4);
- });
- });
- });
- });
- // 1. 定义生成器函数
- function* excuteCode() {
- const res1 = yield requestHttp('http://');
- console.log('res1', res1); // res1 http://
-
- const res2 = yield requestHttp(res1 + 'www');
- console.log('res2', res2); // res2 http://www
-
- const res3 = yield requestHttp(res2 + '.baidu.');
- console.log('res3', res3); // res3 http://www.baidu.
-
- const res4 = yield requestHttp(res3 + 'com');
- console.log('res4', res4); // res4 http://www.baidu.com
- }
-
- // 2. 封装自动执行函数,把生成器函数传入
- function autoExcute(generatorFn) {
- // 3. 拿到生成器对象
- const excuteIterator = generatorFn();
- // 4. 定义递归函数,一次一次调用next方法
- function deepFn(url = '') {
- // { done: true/false, value: 值/undefined }
- const result = excuteIterator.next(url);
- // 执行完成时,done为true,直接返回
- if (result.done) {
- return;
- }
- // 没执行完,继续执行
- result.value.then((url) => {
- deepFn(url);
- });
- }
- // 5. 执行递归函数
- deepFn();
- }
-
- // 6. 开始执行函数
- autoExcute(excuteCode);
- // 1. 定义执行的函数
- async function excuteCode() {
- // 2. 第一次请求
- const res1 = await requestHttp('http://');
- console.log('res1', res1); // res1 http://
-
- // 3. 第二次请求
- const res2 = await requestHttp(res1 + 'www');
- console.log('res2', res2); // res2 http://www
-
- // 3. 第三次请求
- const res3 = await requestHttp(res2 + '.baidu.');
- console.log('res3', res3); // res3 http://www.baidu.
-
- // 4. 第三次请求
- const res4 = await requestHttp(res3 + 'com');
- console.log('res4', res4); // res4 http://www.baidu.com
- }
-
- // 5. 执行代码
- excuteCode();
async关键字用于声明一个异步函数
async : 是asynchronous单词的缩写,异步、非同步
sync : 是synchronous单词的缩写,同步、同时
- async function foo() {}
-
- foo();
const bar = async function() {}
const baz = async () => {}
- class Person {
- async running() {}
- }
异步函数的返回值 : 一定是一个promise对象
异步函数的返回值 : 一定是一个promise对象
异步函数的返回值相当于被包裹到Promise.resolve,相当于 => Promise.resolve( 普通值 )
- async function foo() {
- // 相当于return Promise.resolve([1])
- return [1];
- }
-
- foo().then((res) => {
- console.log(res);
- });
如果返回值是Promise,状态由会由返回的Promise决定
- async function foo() {
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve('冲冲冲');
- }, 3000);
- });
- }
-
- foo().then((res) => {
- console.log(res);
- });
返回值是一个对象并且实现了thenable,那么会由对象的then方法来决定
- async function foo() {
- return {
- then(resolve) {
- setTimeout(() => {
- resolve('无敌');
- }, 5000);
- }
- };
- }
-
- foo().then((res) => {
- console.log(res);
- });
-
如果在async中抛出了异常,那么程序它并不会像普通函数一样报错,这个异常不会被立即浏览器处理
而是会作为Promise的reject来传递 => Promise.reject(error)
- async function foo() {
- console.log('111');
- // 1. 抛出异常
- return new Promise((_, reject) => {
- reject('err');
- });
- }
-
- foo()
- .then((res) => {
- console.log(res);
- })
- .catch((err) => {
- // 2. 这里可以捕获
- console.log(err);
- });
- async function foo() {
- console.log('111');
- // 1. 抛出异常
- throw new Error('我错了');
- console.log('222');
- }
-
- foo()
- .then((res) => {
- console.log(res);
- })
- .catch((err) => {
- // 2. 这里可以捕获
- console.log('oh', err);
- });
async函数可以在它内部使用await关键字,而普通函数中是不可以的
await后续返回一个Promise, 那么会等待Promise有结果之后, 才会继续执行后续的代码
- function bar() {
- console.log('bar function');
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve(123);
- }, 2000);
- });
- }
-
- // await条件: 必须在异步函数中使用
- async function foo() {
- console.log('-------');
- // await后续返回一个Promise, 那么会等待Promise有结果之后, 才会继续执行后续的代码
- const res1 = await bar();
- console.log('await后面的代码:', res1);
- const res2 = await bar();
- console.log('await后面的代码:', res2);
-
- console.log('-------');
- }
- foo();
- function requestData(url) {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- resolve(url)
- }, 2000);
- })
- }
-
- async function getData() {
- // 等待两秒,拿到url的值后才会继续执行
- const res1 = await requestData("coder")
- console.log("res1:", res1)
- // 这里同样等待两秒
- const res2 = await requestData(res1 + "star")
- console.log("res2:", res2)
- }
- function requestData(url) {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- // 1. 如果发生报错
- reject('error message');
- }, 2000);
- });
- }
-
- // 2. 如果发生报错
- async function getData() {
- try {
- const res1 = await requestData('coder');
- console.log('res1:', res1);
- const res2 = await requestData(res1 + 'star');
- console.log('res2:', res2);
- } catch (error) {
- // 01 - 这里可以捕获
- console.log('err:', error);
- }
- }
-
- // 02 - 这里也可以捕获
- getData().catch((error) => {
- console.log('err:', err);
- });
通常await后面会跟上一个表达式 :
await会等,等待有个人把值给它!!!
就像生成器函数中的,yield
- async function foo() {
- // 一般不这么写,和直接赋值没有区别
- const a = await 123;
- console.log(a); // 123
- }
-
- console.log('foo', foo()); // foo Promise {
}
- async function foo() {
- // 等待两秒后拿到值
- const a = await {
- then(resolve) {
- setTimeout(() => {
- resolve(123);
- }, 2000);
- }
- };
- console.log(a); // 123
- }
-
- console.log('foo', foo()); // foo Promise {
}
- async function foo() {
- // 等待两秒
- const a = await new Promise((resolve) => {
- setTimeout(() => {
- resolve(123);
- }, 2000);
- });
- console.log(a); // 123
- }
-
- console.log('foo', foo()); // foo Promise {
}
- async function foo() {
- // 等待两秒
- const a = await new Promise((resolve, reject) => {
- setTimeout(() => {
- reject(123);
- }, 2000);
- });
- // 这里不会运行,直接一层一层往上抛错误,因为异步函数返回值为promise,所以可以在外面捕获
- console.log(a);
- }
-
- foo().catch((err) => {
- console.log(err);
- });
因为异步函数的返回值一定是个promise,所以await会等待该promise的状态确定
一旦确定下来,就会拿到相当于是promise.then中解析出的值
- // 1.普通函数返回promise对象
- function requestData(url) {
- console.log('request data');
- return {
- then(resolve) {
- setTimeout(() => {
- resolve(987);
- }, 2000);
- }
- };
- }
- // 2. 异步函数返回普通的值
- async function test() {
- console.log('test function');
- // 相当于返回的是 Promise.resolve('test')
- return 'test';
- }
-
- // 3. 异步函数|普通函数返回promise对象
- async function bar() {
- console.log('bar function');
- return new Promise((resolve) => {
- setTimeout(() => {
- resolve('bar');
- }, 2000);
- });
- }
-
- // 4. 异步函数|普通函数返回thenable对象
- async function demo() {
- console.log('demo function');
- return {
- then: function (resolve) {
- resolve('demo');
- }
- };
- }
-
- // 3.调用的入口async函数
- async function foo() {
- console.log('foo function');
- // 直接返回值
- const res1 = await requestData('coder');
- console.log('res1:', res1);
- // 直接返回值
- const res2 = await test();
- console.log('res2:', res2);
-
- // 会等待promise的状态确定后,才继续执行
- const res3 = await bar();
- console.log('res3:', res3);
-
- // 会等待thenable的状态确定后,才继续执行
- const res4 = await demo();
- console.log('res4:', res4);
- }
- // 执行
- foo();