之前一章說了generator函數(shù)yield的用法恍风,看了之后完全不知道generator函數(shù)有什么用沟堡,畢竟一步步的next驻售,還不如我直接調(diào)用函數(shù)熟菲。仔細(xì)看了書中的示例看政,總算是有了頭緒。我們先看這段代碼
var fetch = require('node-fetch')
function* gen() {
// 地址瞎寫的別當(dāng)真
var url = 'https://zheshiyigeurl.com'
var result = yield fetch(url)
console.log(result)
}
var g = gen()
g.next()
// 下面這個(gè)塞入回調(diào)函數(shù) 就變成同步了
g.next()
這里的fetch是一個(gè)異步操作抄罕,返回Promise對象允蚣。在我們第一次調(diào)用next的時(shí)候,fetch會(huì)被執(zhí)行呆贿。第二次調(diào)用next的時(shí)候console.log會(huì)執(zhí)行嚷兔。而result會(huì)是一個(gè)Promise對象,在這種調(diào)用方式下做入,generator函數(shù)感覺就是廢冒晰,不明所以。但我們想想竟块,這種調(diào)用的精髓就在于yield的時(shí)候翩剪,gen函數(shù)是被暫停了,如果我們要實(shí)現(xiàn)同步操作彩郊,我們只需要等待足夠的時(shí)間前弯,確保異步操作已經(jīng)完成后,再調(diào)用next就可以了秫逝。但問題的關(guān)鍵是我們怎么知道異步的fetch是在什么時(shí)候完成的吶恕出。所以實(shí)現(xiàn)generator同步的關(guān)鍵點(diǎn)就變成了:
- 使用yield暫停函數(shù)
- 等待異步完成后再執(zhí)行next函數(shù)
那么接下來就是誰能知道異步已經(jīng)完成吶,答案很簡單违帆,異步自己才知道浙巫,也就是回調(diào)函數(shù),當(dāng)異步完成的時(shí)候刷后,他會(huì)調(diào)用回調(diào)函數(shù)的畴,那么我們要做的就是把next塞到異步回調(diào)函數(shù)中。
那么我們改改上面的函數(shù)尝胆,如下:
var fetch = require('node-fetch')
function* gen() {
// 地址瞎寫的別當(dāng)真
var url = 'https://zheshiyigeurl.com'
var result = yield fetch(url)
console.log(result)
}
var g = gen()
g.next().value.then((err, res) => {
g.next(res)
})
到這里我們有遇見了一個(gè)問題丧裁,那就是雖然gen函數(shù)變成同步函數(shù)了,但是我們外面的這個(gè)調(diào)用就很尷尬了含衔,如果gen中有多個(gè)異步操作煎娇,那么外面的調(diào)用會(huì)陷入回調(diào)地獄中。類似于這樣
g.next().value.then((err, res) => {
g.next(res).value.then((err, res) => {
g.next(res).value.then((err, res) => {
g.next(res).value.then(...)
})
})
})