mck*_*k89 218 javascript yield keyword
我在JavaScript中听说过"yield"关键字,但我发现它的文档很差.有人可以解释我(或推荐一个解释的网站)其用途及其用途吗?
bis*_*hop 185
迟到的回答,可能yield
现在每个人都知道,但一些更好的文档已经出现.
修改James Long的"Javascript未来:发电机"中的一个例子,用于官方Harmony标准:
function * foo(x) {
while (true) {
x = x * 2;
yield x;
}
}
Run Code Online (Sandbox Code Playgroud)
"当你调用foo时,你会得到一个具有下一个方法的Generator对象."
var g = foo(2);
g.next(); // -> 4
g.next(); // -> 8
g.next(); // -> 16
Run Code Online (Sandbox Code Playgroud)
所以yield
有点像return
:你得到回报. return x
返回值的值x
,但yield x
返回一个函数,它为您提供了迭代下一个值的方法.如果您有可能要在迭代期间中断的潜在内存密集型过程,则非常有用.
Mat*_*all 81
该MDN文档是相当不错的,海事组织.
包含yield关键字的函数是一个生成器.当你调用它时,它的形式参数绑定到实际的参数,但它的实体并没有被实际评估.而是返回一个generator-iterator.每次调用generator-iterator的next()方法都会执行迭代算法的另一次传递.每个步骤的值是yield关键字指定的值.将yield视为返回的generator-iterator版本,指示算法的每次迭代之间的边界.每次调用next()时,生成器代码将从yield之后的语句中恢复.
Lea*_*der 53
简化/阐述Nick Sotiros的答案(我认为很棒),我认为最好描述一下如何开始编码yield
.
在我看来,使用的最大优点yield
是它将消除我们在代码中看到的所有嵌套回调问题.一开始很难看出,这就是为什么我决定写这个答案(为了我自己,希望是其他人!)
它的实现方式是引入一个协同例程的概念,这个函数可以自动停止/暂停,直到它得到它需要的东西.在javascript中,这表示为function*
.只有function*
功能可以使用yield
.
这是一些典型的javascript:
loadFromDB('query', function (err, result) {
// Do something with the result or handle the error
})
Run Code Online (Sandbox Code Playgroud)
这很笨重,因为现在你所有的代码(显然需要等待这个loadFromDB
调用)都需要在这个丑陋的回调中.由于一些原因,这很糟糕......
})
,你需要跟踪到处function (err, result)
行话result
另一方面,借助于良好的协同例程框架yield
,所有这些都可以在一行中完成.
function* main() {
var result = yield loadFromDB('query')
}
Run Code Online (Sandbox Code Playgroud)
因此,当需要等待变量和事物加载时,您的主函数将在必要时生成.但是现在,为了运行它,你需要调用一个普通的(非协程函数).一个简单的协同例程框架可以解决这个问题,所以你要做的就是运行:
start(main())
Run Code Online (Sandbox Code Playgroud)
并开始定义(来自Nick Sotiro的回答)
function start(routine, data) {
result = routine.next(data);
if(!result.done) {
result.value(function(err, data) {
if(err) routine.throw(err); // continue next iteration of routine with an exception
else start(routine, data); // continue next iteration of routine normally
});
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以拥有更易读,更易删除的漂亮代码,而且无需使用缩进,函数等.
一个有趣的观察是,在这个例子中,yield
实际上只是一个关键字,你可以放在一个带回调的函数之前.
function* main() {
console.log(yield function(cb) { cb(null, "Hello World") })
}
Run Code Online (Sandbox Code Playgroud)
会打印"Hello World".所以你可以yield
通过简单地创建相同的函数签名(没有cb)并返回来实际将任何回调函数转换为使用function (cb) {}
,如下所示:
function yieldAsyncFunc(arg1, arg2) {
return function (cb) {
realAsyncFunc(arg1, arg2, cb)
}
}
Run Code Online (Sandbox Code Playgroud)
希望有了这些知识,您可以编写更易于删除的更清晰,更易读的代码!
noe*_*han 53
这真的很简单,这是它的工作原理
yield
关键字只是有助于在任何时间异步暂停和恢复功能.采取这个简单的生成器功能
function* process() {
console.log('Start process 1');
console.log('Pause process2 until call next()');
yield;
console.log('Resumed process2');
console.log('Pause process3 until call next()');
let parms = yield {age: 12};
console.log("Passed by final process next(90): " + parms);
console.log('Resumed process3');
console.log('End of the process function');
}
let _process = process();
let out1 = _process.next();
console.log(out1);
let out2 = _process.next();
console.log(out2);
let out3 = _process.next(90);
console.log(out3);
Run Code Online (Sandbox Code Playgroud)
let _process = process();
在调用_process.next()之前,它不会执行前两行代码,然后第一个yield会暂停该函数.要恢复该功能直到下一个暂停点(yield关键字),您需要调用_process.next().
您可以认为多个yield是单个函数中javascript调试器中的断点.直到你告诉导航下一个断点,它才会执行代码块.(注意:不阻止整个应用程序)
但是,虽然yield执行此暂停并恢复行为,但它可以返回一些结果,{value: any, done: boolean}
根据之前的函数我们没有发出任何值.如果我们探索先前的输出,它将显示相同{ value: undefined, done: false }
的值undefined.
让我们深入了解yield关键字.(可选)您可以添加表达式并设置分配默认可选值.(官方doc语法)
[rv] = yield [expression];
Run Code Online (Sandbox Code Playgroud)
expression:从生成器函数返回的值
yield any;
yield {age: 12};
Run Code Online (Sandbox Code Playgroud)
rv:返回传递给生成器的next()方法的可选值
只需使用此机制将参数传递给process()函数,即可执行不同的屈服部分.
let val = yield 99;
_process.next(10);
now the val will be 10
Run Code Online (Sandbox Code Playgroud)
用法
参考文献:
Dav*_*vid 18
给出一个完整的答案:yield
工作类似return
,但在发电机中.
至于常见的例子,这可以如下工作:
function *squareGen(x) {
var i;
for (i = 0; i < x; i++) {
yield i*i;
}
}
var gen = squareGen(3);
console.log(gen.next().value); // prints 0
console.log(gen.next().value); // prints 1
console.log(gen.next().value); // prints 4
Run Code Online (Sandbox Code Playgroud)
但是这也是yield关键字的第二个目的.它可用于将值发送到生成器.
澄清一个小例子:
function *sendStuff() {
y = yield (0);
yield y*y;
}
var gen = sendStuff();
console.log(gen.next().value); // prints 0
console.log(gen.next(2).value); // prints 4
Run Code Online (Sandbox Code Playgroud)
这工作,作为值2
分配给y
由它发送到发电机,它停在第一个收益率(其中返回后0
).
这使我们能够获得一些非常时髦的东西.(查找协程)
Han*_*bib 12
Yield
javaScript 函数中的关键字使其成为生成器,
JavaScript 中的生成器是什么?
生成器是产生一系列结果而不是单个值的函数,即您生成一系列值
意义生成器帮助我们与帮助迭代器异步工作,哦,现在黑客迭代器是什么?真的吗?
迭代器是平均的,通过它我们可以一次访问一个项目
迭代器从哪里帮助我们一次访问一个项目?它帮助我们通过生成器函数访问项目,生成器函数是我们使用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
Run Code Online (Sandbox Code Playgroud)
让我简单解释一下发生了什么
您注意到每个yield
关键字的执行都被暂停,我们可以yield
在迭代器的帮助下首先访问.next()
这一次迭代到所有yield
关键字,然后在没有更多yield
关键字时返回 undefined在简单的单词中您可以说yield
关键字是断点,其中函数每次暂停并且仅在使用迭代器调用它时恢复我们的情况:_getMeDrink.next()
这是示例帮助我们访问函数中的每个断点的迭代器。
生成器示例:
async/await
如果你看到你的实现async/await
你会看到generator functions & promises
被用来制作async/await
工作请指出任何建议是受欢迎的。
yield
也可以用一个协程框架来消除回调地狱.
function start(routine, data) {
result = routine.next(data);
if(!result.done) {
result.value(function(err, data) {
if(err) routine.throw(err); // continue next iteration of routine with an exception
else start(routine, data); // continue next iteration of routine normally
});
}
}
// with nodejs as 'node --harmony'
fs = require('fs');
function read(path) {
return function(callback) { fs.readFile(path, {encoding:'utf8'}, callback); };
}
function* routine() {
text = yield read('/path/to/some/file.txt');
console.log(text);
}
// with mdn javascript 1.7
http.get = function(url) {
return function(callback) {
// make xhr request object,
// use callback(null, resonseText) on status 200,
// or callback(responseText) on status 500
};
};
function* routine() {
text = yield http.get('/path/to/some/file.txt');
console.log(text);
}
// invoked as.., on both mdn and nodejs
start(routine());
Run Code Online (Sandbox Code Playgroud)
使用yield关键字的斐波那契数列生成器。
function* fibonacci() {
var a = -1, b = 1, c;
while(1) {
c = a + b;
a = b;
b = c;
yield c;
}
}
var fibonacciGenerator = fibonacci();
fibonacciGenerator.next().value; // 0
fibonacciGenerator.next().value; // 1
fibonacciGenerator.next().value; // 1
fibonacciGenerator.next().value; // 2
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
104365 次 |
最近记录: |