生成器异步处理
普通处理方案
学完了我们前面的Promise、生成器等,我们目前通过一个案例来看一下异步代码的处理方案。
案例需求 :
- 我们需要向服务器发送网络请求获取数据,一共需要发送三次请求;
- 第二次的请求url依赖于第一次的结果;
- 第三次的请求url依赖于第二次的结果, 依次类推;
方式一 : 层层嵌套(回调地狱)
// 封装函数模拟网络请求
function requestDate(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(url)
}, 2000)
})
}
function getData() {
// 发送第一次网络请求
requestDate("aaa").then(res1 => {
console.log("第一次网络请求的结果:", res1) // aaa
// 发送第二次网络请求
requestDate(res1 + "bbb").then(res2 => {
console.log("第二次网络请求的结果:", res2) // aaabbb
// 发送第三次网络请求
requestDate(res2 + "ccc").then(res3 => {
console.log("第三次网络请求的结果:", res3) // aaabbbccc
})
})
})
}
getData()
方式二: 使用Promise进行优化, 解决回调地狱(链式编程)
// 封装函数模拟网络请求
function requestDate(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(url)
}, 2000)
})
}
function getData() {
requestDate("aaa").then(res1 => {
console.log("第一次网络请求的结果:", res1) // aaa
return requestDate(res1 + "bbbb")
}).then(res2 => {
console.log("第二次网络请求的结果:", res2) // aaabbb
return requestDate(res2 + "ccc")
}).then(res3 => {
console.log("第三次网络请求的结果:", res3) // aaabbbccc
})
}
getData()
生成器方案
上面的代码即使方式二使用Promise对代码进行了重构, 但是代码看起来也是阅读性依然比较差的,有没有办法可以继续来对上面的代码进行优化呢?
- 方式三: 利用生成器再进一步的优化
// 封装函数模拟网络请求
function requestDate(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(url)
}, 2000)
})
}
function* getData() {
const res1 = yield requestDate("aaa")
console.log("res1", res1) // aaa
const res2 = yield requestDate(res1 + "bbb")
console.log("res2", res2) // aaabbb
const res3 = yield requestDate(res2 + "ccc")
console.log("res3:", res3) // aaabbbccc
}
const generator = getData()
// 因为生成器的next方法返回的对象中的value值是返回的Promise
// 我们可以通过Promise的then拿到第一次网络请求的结果res1
generator.next().value.then(res1 => {
// 将第一次网络请求的结果传入生成器函数时, 可以拿到第二次网络请求的结果
generator.next(res1).value.then(res2 => {
// 将第二次网络请求的结果传入生成器函数, 可以拿到第三次网络请求的结果
generator.next(res2).value.then(res3 => {
// 将第三次网络请求的结果传入生成器函数
generator.next(res3)
})
})
})
目前我们的方案三写法有两个问题:
- 第一,我们不能确定到底需要调用几层的Promise关系;
- 第二,如果还有其他需要这样执行的函数,我们应该如何操作呢?
所以,我们可以封装一个工具函数execGenerator自动执行生成器函数(了解):
// 封装模拟网络请求的函数
function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(url)
}, 2000)
})
}
// 生成器的处理方案
function* getData() {
const res1 = yield requestData("why")
console.log("res1:", res1)
const res2 = yield requestData(res1 + "kobe")
console.log("res2:", res2)
const res3 = yield requestData(res2 + "james")
console.log("res3:", res3)
const res4 = yield requestData(res3 + "curry")
console.log("res4:", res4)
const res5 = yield requestData(res4 + "tatumu")
console.log("res5:", res5)
}
// 自动化执行生成器函数(了解)
function execGenFn(genFn) {
// 1.获取对应函数的generator
const generator = genFn()
// 2.定义一个递归函数
function exec(res) {
const result = generator.next(res)
if (result.done) return
result.value.then(res => {
exec(res)
})
}
// 3.执行递归函数
exec()
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/120128.html