1보 전진과 2보 후퇴?
“그냥 세 개의 파일을 동시에 읽으면 더 효율적이지 않나?” 예리한 질문도 있을 수 있습니다. 그 질문에 대한 답은 문제에 따라, 자바스크립트 엔진에 따라, 운영체제에 따라, 파일 시스템에 따라 크게 다를 수 있습니다. 하지만 복잡한 부분은 잠시 미뤄두고, 세 파일을 읽는 순서는 상관이 없다는 것, 그리고 설령 세 파일을 동시에 읽었다 한들 과연 효율적일지는 의문스럽다는 점을 상기합시다. theFutureIsNow 함수를 이런 식으로 만든 것은, 이 방법이 이해하기 쉽고 단순해 보였기 때문입니다.
Promise에는 all 메서드가 있습니다. 이 메서드는 배열로 받는 프라미스가 모두 완료될 때 완료되며, 가능하다면 비동기적 코드를 동시에 실행합니다. theFutureIsNow 함수가 Promise.all을 사용하도록 수정하기만 하면 됩니다.
function* theFutureIsNow() {
const data = yield Promise.all([
yield nfcall(fs.readFile, 'a.txt'),
yield nfcall(fs.readFile, 'b.txt'),
yield nfcall(fs.readFile, 'c.txt'),
]);
yield ptimeout(60*1000);
yield nfcall(fs.writeFile, 'd.txt'. dataA+dataB+dataC);
}
Promise.all이 반환하는 프라미스에는 매개변수로 주어진 각 프라미스의 완료 값이 배열에 들어있었던 순서대로 들어있습니다. c.txt를 a.txt보다 먼저 읽더라도 data[0]에는 a.txt의 내용이, data[2]에는 c.txt의 내용이 들어 있습니다.
Promise.all은 편리한 도구이고 알아두면 좋지만, 이 섹션에서 가장 중요한 것은 Promise.all이 아닙니다. 이 섹션에서 가장 중요한 것은 프로그램에서 어떤 부분을 동시에 실행할 수 있고 어떤 부분은 동시에 실행할 수 없는지를 판단하는 것이어야 합니다. 이 예제에서는 파일을 읽는 것과 타임아웃이 동시에 실행되더라도 상관없습니다. 어떤 부분을 동시에 실행할 수 있고 어떤 부분은 동시에 실행할 수 없는지를 판단하는 것은 문제에 따라 다릅니다. 세 파일을 읽은 다음에 60초를 기다리고 그 다음에 병합 결과를 파일에 저장하는 것이 중요하다면 그 답은 이미 예제에 들어있습니다. 반면 세 파일을 읽는 것과 무관하게 60초 이상이 흐른 다음 네 번째 파일에 결과를 저장하는 것이 중요하다면 타임아웃을 Promise.all로 옮기는 편이 좋을 겁니다.