zhuanghaixin / Interview

8 stars 0 forks source link

[js/异步] 你知道Genearator? #86

Open zhuanghaixin opened 3 years ago

zhuanghaixin commented 3 years ago

基本概念

Generator 函数是 ES6 提供的一种异步编程解决方案

例子1,函数不会立即执行,而是生成一个Generator迭代器对象

function* foo(){
for(let i=0;i<3;i++){
console.log(i)
yield i
}
}
// console.log(foo())
let f=foo()
console.log(f.next());
console.log(f.next())
console.log(f.next())
console.log(f.next())

image

例子2 yield关键字只能在生成器内部使用

function* gen(args) {
    args.forEach(item => {
        yield item + 1
    })
}
let g=gen()

console.log(g.next())
function* gen(args) {
    args.forEach(item => {
        yield item + 1
    })
}
let g=gen()

console.log(g.next())

image

例子3 next()不传参数

function* gen(x) {
    let y = 2 * (yield(x + 1))
    let z = yield(y / 3)
    return x + y + z
}

let g=gen(5)
console.log(g.next())  // 6
console.log(g.next())  // NaN
console.log(g.next()) // NaN
console.log(g.next())

image

例子4 next()传参数 yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。


function* gen(x) {
    let y = 2 * (yield(x + 1))
    let z = yield(y / 3)
    return x + y + z
}

let g=gen(5)
console.log(g.next()) //x=5 6
console.log(g.next(12)) // y=24 8
console.log(g.next(13)) // z=13 6+24+13=42
console.log(g.next())

例子5 找到7的倍数的数

function* count(x=1){
    while(true){
        if(x%7==0){
            yield x

        }
        x++
    }
}

let n=count()
console.log(n.next().value);
console.log(n.next().value);
console.log(n.next().value);
console.log(n.next().value);

image

zhuanghaixin commented 3 years ago

genenertor ajax请求a,b,c 三个文件,依次请求

错误的例子

function ajax(url, callback) {
    // 1、创建XMLHttpRequest对象
    var xmlhttp
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest()
    } else { // 兼容早期浏览器
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
    }
    // 2、发送请求
    xmlhttp.open('GET', url, true)
    xmlhttp.send()
    // 3、服务端响应
    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            var obj = JSON.parse(xmlhttp.responseText)
            // console.log(obj)
            callback(obj)
        }
    }
}

function request(url) {
    ajax(url, res => {
        console.log(res)
    })

}

function* gen() {
    let res1 = yield request('static/a.json')
    console.log(res1)
    let res2 = yield request('static/b.json')
    console.log(res2)
    let res3 = yield request('static/c.json')
    console.log(res3)
}

let getData = gen();
console.log(getData.next())
console.log(getData.next())
console.log(getData.next())
console.log(getData.next())

image 虽然后面console.log()是同步的,但是yiedl表达式是request是异步的,所以还是输出不同的结果

正确的例子

function request(url) {
    ajax(url, res => {

        getData.next(res)  //第二次执行 下一个yield yield request('static/b.json')   第三次执行
    })

}

function* gen() {
    let res1 = yield request('static/a.json')
    console.log(res1)
    let res2 = yield request('static/b.json')
    console.log(res2)
    let res3 = yield request('static/c.json')
    console.log(res3)
}

let getData = gen();
console.log(getData.next())  //第一次执行

image