[javascript] JavaScript에서 yield 키워드는 무엇입니까?
JavaScript에서 “yield”키워드에 대해 들었지만 그에 대한 문서가 매우 부족했습니다. 누군가 나에게 사용법과 용도를 설명 할 수 있습니까?
답변
MDN 문서는 IMO, 아주 좋은 것입니다.
yield 키워드를 포함하는 함수는 생성기입니다. 호출하면 형식 매개 변수는 실제 인수에 바인딩되지만 본문은 실제로 평가되지 않습니다. 대신 생성기-반복기가 리턴됩니다. generator-iterator의 next () 메소드를 호출 할 때마다 반복 알고리즘을 통해 다른 패스를 수행합니다. 각 단계의 값은 yield 키워드로 지정된 값입니다. yield를 생성기-반복기 버전의 리턴으로 생각하여 알고리즘의 각 반복 사이의 경계를 나타냅니다. next ()를 호출 할 때마다 생성기 코드는 수율에 따라 명령문에서 재개됩니다.
답변
늦게 대답하면 아마 모든 사람들이 yield
지금 알고 있지만 더 나은 문서가 나왔습니다.
공식 하모니 표준을 위해 James Long 의 “Javascript ‘s Future : Generators” 에서 예를 채택 :
function * foo(x) {
while (true) {
x = x * 2;
yield x;
}
}
“foo를 호출하면 다음 메소드가있는 Generator 객체를 다시 얻게됩니다.”
var g = foo(2);
g.next(); // -> 4
g.next(); // -> 8
g.next(); // -> 16
그래서 yield
일종의 같은 것입니다 return
: 당신은 무언가를 되 찾습니다. return x
의 값을 반환 x
하지만 yield x
다음 값으로 반복 할 수있는 메서드를 제공하는 함수를 반환합니다. 반복 중에 중단 할 수 있는 메모리 집약적 인 프로 시저 가있는 경우 유용합니다 .
답변
정말 간단합니다. 이것이 작동하는 방식입니다
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 ();
당신이 호출 할 때까지 () _process.next 가 실 거예요 실행] 처음 2 줄 의 코드를 다음 첫 번째 수율이 됩니다 일시 정지 기능을. 다음 일시 정지 지점 ( yield 키워드 ) 까지 함수 를 재개 하려면 _process.next () 를 호출해야합니다 .
단일 함수 내에서 자바 스크립트 디버거 의 여러 수율 이 중단 점 이라고 생각할 수 있습니다 . 다음 중단 점을 탐색하도록 지시 할 때까지 코드 블록을 실행하지 않습니다. ( 참고 : 전체 응용 프로그램을 차단하지 않고)
그러나 yield는 이러한 일시 정지 및 재개 동작을 수행하지만
이전 함수에 따라 값을 생성하지 않은 결과 를 반환 할 수 있습니다 {value: any, done: boolean}
. 이전 출력을 살펴보면 undefined{ value: undefined, done: false }
값과 동일하게 표시됩니다 .
yield 키워드를 파헤칩니다. 선택적으로 expression 을 추가 하고 기본 선택적 값을 지정하도록 설정할 수 있습니다 . (공식 문서 구문)
[rv] = yield [expression];
expression : 생성기 함수에서 반환 할 값
yield any;
yield {age: 12};
rv : 생성기 next () 메소드에 전달 된 선택적 값을 리턴합니다.
이 메커니즘을 사용하여 process () 함수에 매개 변수를 전달하여 다른 항복 파트를 실행할 수 있습니다.
let val = yield 99;
_process.next(10);
now the val will be 10
사용법
- 게으른 평가
- 무한 시퀀스
- 비동기 제어 흐름
참고 문헌 :
답변
Nick Sotiros의 답변을 단순화 / 정교하게 만드는 방법은 훌륭하다고 생각합니다 yield
.
내 의견으로는, 사용의 가장 큰 장점 yield
코드에서 볼 수있는 모든 중첩 콜백 문제를 제거한다는 것입니다. 처음에는 방법을 알기가 어렵 기 때문에이 답변을 작성하기로 결정했습니다 (나 자신과 다른 사람들을 위해)!
이를 수행하는 방법은 필요한 것을 얻을 때까지 자발적으로 중지 / 일시 정지 할 수있는 기능인 공동 루틴 아이디어를 도입하는 것입니다. 자바 스크립트에서 이는로 표시됩니다 function*
. function*
기능 만 사용할 수 있습니다 yield
.
다음은 일반적인 자바 스크립트입니다.
loadFromDB('query', function (err, result) {
// Do something with the result or handle the error
})
이제 모든 코드 (이 loadFromDB
호출 을 기다려야 함 ) 가보기 흉한 콜백 안에 있어야하기 때문에 이것은 복잡합니다 . 몇 가지 이유로 나쁘다 …
- 모든 코드는 한 수준으로 들여 쓰기됩니다
- 당신은 당신이
})
어디서나 추적 해야하는 이 끝 이있다 - 이 모든 추가
function (err, result)
전문 용어 - 값을 할당하기 위해이 작업을 수행하고 있음을 정확히 알 수는 없습니다.
result
반면 에을 사용하면 멋진 공동 루틴 프레임 워크를 사용하여 한 줄yield
로이 모든 작업을 수행 할 수 있습니다 .
function* main() {
var result = yield loadFromDB('query')
}
따라서 이제 주요 함수는 변수와로드 될 때까지 기다려야 할 때 필요한 곳에서 생성됩니다. 그러나 이제 이것을 실행하려면 일반 (비 병렬 함수) 을 호출해야합니다 . 간단한 공동 루틴 프레임 워크로이 문제를 해결할 수 있으므로 다음을 실행하면됩니다.
start(main())
그리고 시작이 정의됩니다 (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
});
}
}
이제 더 읽기 쉽고 삭제하기 쉽고 들여 쓰기, 함수 등으로 바이올린을 칠 필요가없는 아름다운 코드를 가질 수 있습니다.
이 예제에서는 yield
실제로 콜백이있는 함수 앞에 넣을 수있는 키워드 일뿐입니다.
function* main() {
console.log(yield function(cb) { cb(null, "Hello World") })
}
“Hello World”를 인쇄합니다. 따라서 실제로 yield
동일한 함수 서명 (cb없이)을 만들고을 반환 하여 콜백 함수를 실제로 사용할 수 있습니다 function (cb) {}
.
function yieldAsyncFunc(arg1, arg2) {
return function (cb) {
realAsyncFunc(arg1, arg2, cb)
}
}
이 지식 으로 삭제하기 쉬운 더 읽기 쉽고 깔끔한 코드를 작성할 수 있기를 바랍니다 .
답변
완전한 대답을 제공하려면 : 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
그러나 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
이 값 2
은에 할당 된 대로 y
첫 번째 수확량 (으로 반환 된 0
) 에서 중지 된 후 생성기로 전송하여 작동합니다 .
이것은 우리에게 정말 펑키 한 것들을 가능하게합니다. (코 루틴 조회)
답변
반복자 생성기에 사용됩니다. 기본적으로 절차 코드를 사용하여 (잠재적으로 무한한) 시퀀스를 만들 수 있습니다. Mozilla 설명서를 참조하십시오 .
답변
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());