我听说过JavaScript中的“yield”关键字,但我发现关于它的文档非常糟糕。有人能给我解释一下(或者推荐一个解释它的网站)它的用法和用途吗?
当前回答
它用于迭代器生成器。基本上,它允许您使用过程代码制作(可能是无限的)序列。请参阅Mozilla的文档。
其他回答
不要忘记使用非常有用的“x of generator”语法来遍历生成器。根本不需要使用next()函数。
function* square(x){
for(i=0;i<100;i++){
x = x * 2;
yield x;
}
}
var gen = square(2);
for(x of gen){
console.log(x);
}
举个简单的例子:
const strArr = ["red", "green", "blue", "black"];
const strGen = function*() {
for(let str of strArr) {
yield str;
}
};
let gen = strGen();
for (let i = 0; i < 5; i++) {
console.log(gen.next())
}
//prints: {value: "red", done: false} -> 5 times with different colors, if you try it again as below:
console.log(gen.next());
//prints: {value: undefined, done: true}
我还试图理解yield关键字。根据我目前的理解,在生成器中,yield关键字就像CPU上下文开关一样。当yield语句运行时,将保存所有状态(例如局部变量)。
除此之外,一个直接的结果对象将返回给调用者,如{value: 0, done: false}。调用者可以使用这个结果对象通过调用next()来决定是否再次“唤醒”生成器(调用next()是为了迭代执行)。
另一个重要的事情是,它可以将一个值设置为一个局部变量。这个值可以在“唤醒”生成器时由“next()”调用者传递。例如,it.next('valueToPass'),就像这样:"resultValue = yield slowQuery(1);"就像唤醒下一次执行时一样,调用者可以向执行注入一些运行结果(注入到局部变量)。因此,对于这个执行,有两种状态:
上次执行时保存的上下文。 这个执行的触发器注入的值。
因此,有了这个特性,生成器可以对多个异步操作进行排序。第一个异步查询的结果将通过设置局部变量(上面例子中的resultValue)传递给第二个异步查询。第二个异步查询只能由第一个异步查询的响应触发。然后第二个异步查询可以检查局部变量值以决定下一步,因为局部变量是第一个查询响应的注入值。
异步查询的困难在于:
回调地狱 除非在回调中将它们作为参数传递,否则将丢失上下文。
产量和发电机可以帮助这两个。
在没有yield和generator的情况下,对多个异步查询进行排序需要以参数为上下文的嵌套回调,不便于读取和维护。
下面是一个使用nodejs运行的链式异步查询示例:
const axios = require('axios');
function slowQuery(url) {
axios.get(url)
.then(function (response) {
it.next(1);
})
.catch(function (error) {
it.next(0);
})
}
function* myGen(i=0) {
let queryResult = 0;
console.log("query1", queryResult);
queryResult = yield slowQuery('https://google.com');
if(queryResult == 1) {
console.log("query2", queryResult);
//change it to the correct url and run again.
queryResult = yield slowQuery('https://1111111111google.com');
}
if(queryResult == 1) {
console.log("query3", queryResult);
queryResult = yield slowQuery('https://google.com');
} else {
console.log("query4", queryResult);
queryResult = yield slowQuery('https://google.com');
}
}
console.log("+++++++++++start+++++++++++");
let it = myGen();
let result = it.next();
console.log("+++++++++++end+++++++++++");
运行结果如下:
+++++++++++ 《削减战略武器条约》 +++++++++++
query1 0
+++++++++++ 新力 +++++++++++
query2 1
query4 0
下面的状态模式可以做类似的事情,上面的例子:
const axios = require('axios');
function slowQuery(url) {
axios.get(url)
.then(function (response) {
sm.next(1);
})
.catch(function (error) {
sm.next(0);
})
}
class StateMachine {
constructor () {
this.handler = handlerA;
this.next = (result = 1) => this.handler(this, result);
}
}
const handlerA = (sm, result) => {
const queryResult = result; //similar with generator injection
console.log("query1", queryResult);
slowQuery('https://google.com');
sm.handler = handlerB; //similar with yield;
};
const handlerB = (sm, result) => {
const queryResult = result; //similar with generator injection
if(queryResult == 1) {
console.log("query2", queryResult);
slowQuery('https://1111111111google.com');
}
sm.handler = handlerC; //similar with yield;
};
const handlerC = (sm, result) => {
const queryResult = result; //similar with generator injection;
if (result == 1 ) {
console.log("query3", queryResult);
slowQuery('https://google.com');
} else {
console.log("query4", queryResult);
slowQuery('https://google.com');
}
sm.handler = handlerEnd; //similar with yield;
};
const handlerEnd = (sm, result) => {};
console.log("+++++++++++start+++++++++++");
const sm = new StateMachine();
sm.next();
console.log("+++++++++++end+++++++++++");
运行结果如下:
+++++++++++ 《削减战略武器条约》 +++++++++++
query1 0
+++++++++++ 新力 +++++++++++
query2 1
query4 0
Yield关键字在javaScript函数使它生成器,
什么是JavaScript生成器?
生成器是产生一系列结果而不是单个值的函数,即您生成一系列值
这意味着生成器可以帮助我们与帮助迭代器异步工作,哦,hack迭代器是什么?真的吗?
迭代器意味着我们可以一次访问一个项
从哪里迭代器可以帮助我们一次访问第一项? 它帮助我们通过生成器函数访问项目,生成器函数中我们使用yield关键字,yield关键字帮助我们暂停和恢复函数的执行。
这里有一个简单的例子:
function *getMeDrink() {
let question1 = yield 'soda or beer'; // execution will pause here because of yield
if (question1 == 'soda') {
return 'here you get your soda';
}
if (question1 == 'beer') {
let question2 = yield 'What\'s your age'; // execution will pause here because of yield
if (question2 > 18) {
return "ok you are eligible for it";
} else {
return "Shhhh!!!!";
}
}
}
let _getMeDrink = getMeDrink(); // initialize it
_getMeDrink.next().value; // "soda or beer"
_getMeDrink.next('beer').value; // "What's your age"
_getMeDrink.next('20').value; // "ok you are eligible for it"
_getMeDrink.next().value; // undefined
让我简单地解释一下发生了什么
你注意到在每个yield关键字处执行被暂停,我们可以通过迭代器.next()访问第一个yield
它一次迭代到所有yield关键字,然后当没有更多的yield关键字时返回undefined,简单地说,你可以说yield关键字是断点,函数每次暂停,只有在使用迭代器调用它时才恢复,对于我们的例子:_getMeDrink.next()这是一个迭代器的例子,它帮助我们访问函数中的每个断点。
生成器示例: 异步/等待
如果你看到async/await的实现,你会看到生成器函数和承诺被用来使async/await工作,请指出任何建议,欢迎。
异步javascript调用之间的依赖关系。
另一个关于如何使用yield的好例子。
函数请求(url) { Axios.get (url).then((response) => { it.next(响应); }) } 函数* main() { Const result1 = yield request('http://some.api.com'); Const result2 = yield request('http://some.otherapi?Id =' + result1。id); console.log('您的响应是:' + result2.value); } Var it = main(); it.next ()
推荐文章
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 我如何等待一个承诺完成之前返回一个函数的变量?
- 在JavaScript中根据键值查找和删除数组中的对象
- 使嵌套JavaScript对象平放/不平放的最快方法
- 如何以及为什么'a'['toUpperCase']()在JavaScript工作?
- 有Grunt生成index.html不同的设置
- 文档之间的区别。addEventListener和window。addEventListener?
- 如何检查动态附加的事件监听器是否存在?
- 如何写setTimeout与参数Coffeescript
- 将JavaScript字符串中的多个空格替换为单个空格
- JavaScript: override alert()
- 重置setTimeout
- 在Python中重置生成器对象
- 如何确保<select>表单字段被禁用时提交?
- jQuery有不聚焦的方法吗?