Javascript 将ES6生成器与XMLHttpRequest一起使用

Javascript 将ES6生成器与XMLHttpRequest一起使用,javascript,ajax,ecmascript-6,generator,Javascript,Ajax,Ecmascript 6,Generator,我试图简化如何使用ES6生成器进行AJAX调用。但是,我遇到了一些问题: let xhr = new XMLHttpRequest() function *statechange() { yield xhr.readyState; } let gen = statechange(); xhr.open("GET", myUrl, true); xhr.onreadystatechange = function() {console.log(gen.next())}; xhr.sen

我试图简化如何使用ES6生成器进行AJAX调用。但是,我遇到了一些问题:

let xhr = new XMLHttpRequest()

function *statechange() {
    yield xhr.readyState;
}

let gen = statechange();

xhr.open("GET", myUrl, true);
xhr.onreadystatechange = function() {console.log(gen.next())};
xhr.send();
我只是简单解释一下我要做的事情:我想给出每个请求状态更改的就绪状态。我在生成器的每次迭代中记录
readyState
字符串。但当我运行此代码时,我得到:

{value: 2, done: false}
{value: undefined, done: true}
{value: undefined, done: true}
从表面上看,这是正确的,但如果我使用老式的XHR:

//... new XMLHttpRequest()...
xhr.onreadystatechange = function() {console.log(xhr.readyState)}
我得到:

2
3
4
所以。。。我使用发电机哪里出了问题


更新:

更奇怪的是,如果我在生成器中记录
readyState

//                                                     HERE
xhr.onreadystatechange = function() {console.log(xhr.readyState, gen.next())};
我明白了:

2, {value: 2, done: false}
3, {value: undefined, done: true}
4, {value: undefined, done: true}
这意味着,当调用
next()
方法时,正确的
readyState
可用。我只能猜测我只使用了一次寄存器的
yield
语句,因此生成器只分配一个插槽。我想既然
onreadystatechange
被多次调用,就会分配更多的插槽。如何解决此问题?

当您“调用”一个生成器函数时,它会一直运行,直到第一个
yield
语句,然后暂停,直到调用了
next
方法。在此之后,它将继续运行,直到出现另一个
yield
语句,或者函数或控件离开函数。在后一种情况下,对
next
方法的所有调用都将返回
undefined

您需要的是在每次迭代中检查xhr的
readyState
的循环:

function *statechange() {
  while(true) { // loop forever
    yield xhr.readyState;
  }
}
如果您熟悉Python中的生成器,则完全相同


我将附议@Paul S.的评论,即这并没有真正简化XHR,您应该查看这方面的承诺。

gen
到达函数的末尾,因此就完成了(同样,这并没有真正简化XHR,而是倾听加载/错误,您可以将它们作为承诺编写)