async/await
在日常开发中我们经常会使用到async/await,以下就是使用场景
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);
// 这里如果p2依赖于p1的成功结果,p3又依赖于p2的成功结果那么就会出现以下情况
// 这种情况下如果还参杂着一些业务逻辑 可读性很差
p1.then((data) => {
p2.then((data2) => {
p3.then((data3) => {
console.log(">>>>>>回调地狱", data3);
});
});
});
// 或者
p1.then((data) => {
return p2;
})
.then((data) => {
return p3;
})
.then((data) => {
console.log(">>>>>>链式调用", data);
});
// 使用async/ await
// 结果和promise是一个样的 但是看着更加简洁一些
async function result2() {
const res1 = await p1;
const res2 = await p2;
const res3 = await p3;
console.log(">>>>>> async/await", res1, res2, res3);
}
console.log(">>>>>>result2", 1,2,3);
async
字面意思就是异步 使用async的函数 返回值是一个Promise对象 async声明的是一个异步构造函数,来看如下示例
const fn1 = async function fn() {
return 1;
};
console.log(">>>>>>>fn1", fn1());
// Promise {<fulfilled>: 1}
这里我们可以看到 使用async包裹的函数返回的是一个Promise对象,那么为什么会return 1会返回一个Promise呢,因为如果这里返回的 不是一个Promise那么这里就会用Promise.resolve(*) 包裹起来
await
字面意思就是等待, 不仅仅等待Promise对象,可以等任何表达式的结果 且只能在async内部使用
const fn2 = function test1() {
return Promise.resolve(1);
};
const fn3 = function test2() {
return "test";
};
async function result() {
const res1 = await fn2();
console.log('>>>>>停一下哥们')
const res2 = await fn3();
console.log(">>>>>>返回结果", res1, res2);
}
result(); // console.log(">>>>>>返回结果", 1, test);
上面代码可以看到 用同步方式,执行异步操作达到排队效果,解决回调地狱 那么这个async/await 是怎么实现的呢下面我们就来说说Generator
Generator
Generator是封装的一个异步任务,或者说是一个异步任务的容器 需要暂停异步任务的地方,可以使用yield语句标明 调用Generator函数返回一个指针对象(这是与其他函数不同的地方), 调用指针对象的next方法,会移动内部指针。
function* gener() {
yield 1;
yield 2;
yield Promise.resolve(3);
return 3;
}
const gen = gener();
console.log("><>>>>>>", gen.next(), 1); // { value: 1, done: false }
console.log("><>>>>>>", gen.next(), 2); // { value: 2, done: false }
console.log("><>>>>>>", gen.next(), 3); // { value: Promise, done: false }
console.log("><>>>>>>", gen.next(), 4); // { value: 3, done: true }
在上面这段代码中可以看到,gener函数返回一个指针对象,调用指针的next 会返回当前阶段的对象 其中value 标识当前的值,done标识完成状态。
看完上面的Generator 函数我们回过头来看看 async/await 是怎么实现的呢,我们可以这样理解
- 1.async 函数执行结果返回的是一个promise
- 2.async 函数就是将Generator函数的星号(*)替换成async,将yield替换成await
- 3.async/await 就是Generator的语法糖,其核心逻辑是迭代执行next函数
首先我们设定一个请求函数
function getFetch(num) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(num + 1);
}, 1000);
});
}
完善一下gener函数,这里说明一下,上面调用gen.next() 如果我们在next(*)传入参数 ,那么就是这个当前yield语句返回值
function* myGen() {
const res1 = yield getFetch(1);
const res2 = yield getFetch(res1);
const res3 = yield getFetch(res2);
return res3;
}
我们再设定一个 myAsync函数
// 接受一个Gennerator函数作为参数
function myAsync(gen) {
// 返回一个函数
return function () {
// 返回一个promis
return new Promise((resolve, reject) => {});
};
}
完善一下 myAsync函数
function myAsync(gen) {
return function () {
return new Promise((resolve, reject) => {
const g = gen();
// 这里的 context 是传递给下一个
const next = (context) => {
let res;
try {
res = g.next(context);
} catch (e) {
reject(e);
}
const { value, done } = res;
// 如果已经完成我们就直接返回成功
if (done) {
resolve(value);
} else {
// 没有完成的话 我们继续递归调用 直到done为true
return Promise.resolve(value).then(
(val) => next(val),
(err) => next(err)
);
}
};
next();
});
};
}
const test = myAsync(myGen);
当然了 上面写的我自己都看的一脸懵逼我只是为了做一下笔记