模拟网络请求
-
网络需求:
-
url: https://neko -> res: https://neko
-
url: https://neko + "aimer" -> res: https://nekoaimer
-
url: https://nekoaimer + ".com" -> res: nekoaimer.com
-
回调地狱问题
- 这种代码阅读性极差
// 网络请求
function requsetDate(url) {
return new Promise(resolve => setTimeout(() => resolve(url), 2000))
}
// 回调地狱
requsetDate('https://neko')
.then(res => {
requsetDate(res).then(res => {
requsetDate(res + 'aimer').then(res => {
requsetDate(res + '.com').then(res => {
console.log(res) // https://nekoaimer.com
})
})
})
})
优化方案
- Promise then方法的返回值也是Promise, 那么我们可以return出去
- 这种方式就要清晰不少,但依然不是我认为最好的处理的方案或者说是结果
// 网络请求
function requsetDate(url) {
return new Promise(resolve => setTimeout(() => resolve(url), 2000))
}
requsetDate('https://neko')
.then(res => {
return requsetDate(res + 'aimer')
})
.then(res => {
return requsetDate(res + '.com')
})
.then(res => {
console.log(res) // https://nekoaimer.com
})
Promise + generator 方案
- 这种方案从 getData() 能够清晰的得出每次结果
// 网络请求
function requsetDate(url) {
return new Promise(resolve => setTimeout(() => resolve(url), 2000))
}
// 这种结构每次网络请求就会看的非常清晰
function* getData() {
const res1 = yield requsetDate('https://neko')
console.log(res1) // https://neko
const res2 = yield requsetDate(res1 + 'aimer')
console.log(res2) // https://nekoaimer
const res3 = yield requsetDate(res2 + '.com')
console.log(res3) // https://nekoaimer.com
}
// generator
const generator = getData()
generator.next().value.then(res => {
generator.next(res).value.then(res => {
generator.next(res).value.then(res => {
generator.next(res)
})
})
})
- 那么有人可能会有疑问了,下面的 generator 不也是回调地狱吗,代码量看上去更麻烦了呀?
- 别急,我会进行一些处理,之后就会发现这种处理方式结构清晰,可重复利用是非常优秀的
自动执行generator函数
// 网络请求
function requsetDate(url) {
return new Promise(resolve => setTimeout(() => resolve(url), 2000))
}
// 封装了一个自动执行的函数
function execGenerator(genFn) {
const generator = genFn()
function exec(res) {
const result = generator.next(res)
if (result.done) return result.value
result.value.then(res => exec(res))
}
exec()
}
// generator 方式代码清晰明了
function* getData() {
const res1 = yield requsetDate('https://neko')
const res2 = yield requsetDate(res1 + 'aimer')
const res3 = yield requsetDate(res2 + '.com')
console.log(res3) // https://nekoaimer.com
}
execGenerator(getData)
co(TJ)
- 安装 co 包
npm install co
- 这个包实现的功能与上面的类似 所以可直接引入进来
function requsetDate(url) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(url), 2000)
})
}
function* getData() {
const res1 = yield requsetDate('https://neko')
const res2 = yield requsetDate(res1 + 'aimer')
const res3 = yield requsetDate(res2 + '.com')
console.log(res3) // https://nekoaimer.com
}
const co = require('co')
co(getData)
async & await 实现
- 这种方案本质上是 generator 与 Promise 的语法糖
- 所以最终的解决方案就是下面这种了
function requsetDate(url) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(url), 2000)
})
}
async function getData() {
const res1 = await requsetDate('https://neko')
const res2 = await requsetDate(res1 + 'aimer')
const res3 = await requsetDate(res2 + '.com')
console.log(res3) // https://nekoaimer.com
}
getData()