[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());