이것이 어떻게 잘못 될 수 있는지 보려면, 메소드의 끝에 console.log를 인쇄하십시오.
일반적으로 잘못 될 수있는 것 :
- 임의의 순서.
- printFiles는 파일을 인쇄하기 전에 실행을 마칠 수 있습니다.
- 성능이 저하됩니다.
항상 잘못된 것은 아니지만 표준 사용 사례에 자주 있습니다.
일반적으로 forEach를 사용하면 마지막을 제외한 모든 결과가 발생합니다. 함수를 기다리지 않고 각 함수를 호출합니다. 즉, 모든 함수가 시작되고 완료 될 때까지 기다리지 않고 완료되도록 지시합니다.
import fs from 'fs-promise'
async function printFiles () {
const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'))
for(const file of files)
console.log(await file)
}
printFiles()
이것은 순서를 유지하고 함수가 조기에 리턴되는 것을 방지하고 이론적으로 최적의 성능을 유지하는 기본 JS의 예입니다.
이것은 :
- 병렬로 발생하는 모든 파일 읽기를 시작하십시오.
- 기다릴 약속으로 파일 이름을 맵핑하기 위해 map을 사용하여 순서를 유지하십시오.
- 배열에서 정의한 순서대로 각 약속을 기다립니다.
이 솔루션을 사용하면 다른 파일이 먼저 사용 가능할 때까지 기다리지 않고 사용 가능한 즉시 첫 번째 파일이 표시됩니다.
또한 두 번째 파일 읽기를 시작하기 전에 첫 번째 파일이 완료 될 때까지 기다리지 않고 모든 파일을 동시에로드합니다.
이것과 원래 버전의 유일한 단점은 한 번에 여러 번 읽기를 시작하면 한 번에 발생할 수있는 더 많은 오류가 있기 때문에 오류를 처리하기가 더 어렵다는 것입니다.
한 번에 파일을 읽는 버전을 사용하면 더 이상 파일을 읽는 데 시간을 낭비하지 않고 오류가 발생하면 중지됩니다. 정교한 취소 시스템을 사용하더라도 첫 번째 파일에서 실패하지만 다른 파일도 대부분 읽는 것을 피하기 어려울 수 있습니다.
성능을 항상 예측할 수있는 것은 아닙니다. 병렬 파일 읽기로 많은 시스템이 더 빠르지 만 일부는 순차적 인 것을 선호합니다. 일부는 동적이며로드 상태에서 전환 될 수 있습니다. 대기 시간을 제공하는 최적화로 인해 경쟁이 심할 때 처리량이 항상 좋은 것은 아닙니다.
이 예에서는 오류 처리도 없습니다. 무언가가 모두 성공적으로 표시되거나 전혀 표시되지 않아야하는 경우 그렇게하지 않습니다.
각 단계에서 console.log 및 가짜 파일 읽기 솔루션 (임의의 지연) 대신 심층적 인 실험이 권장됩니다. 많은 경우에 간단한 해결책으로도 많은 솔루션이 동일한 것으로 보이지만 모두 약간의 정밀한 조사가 필요한 미묘한 차이가 있습니다.
이 모의를 사용하여 솔루션 간의 차이점을 알 수 있습니다.
(async () => {
const start = +new Date();
const mock = () => {
return {
fs: {readFile: file => new Promise((resolve, reject) => {
// Instead of this just make three files and try each timing arrangement.
// IE, all same, [100, 200, 300], [300, 200, 100], [100, 300, 200], etc.
const time = Math.round(100 + Math.random() * 4900);
console.log(`Read of ${file} started at ${new Date() - start} and will take ${time}ms.`)
setTimeout(() => {
// Bonus material here if random reject instead.
console.log(`Read of ${file} finished, resolving promise at ${new Date() - start}.`);
resolve(file);
}, time);
})},
console: {log: file => console.log(`Console Log of ${file} finished at ${new Date() - start}.`)},
getFilePaths: () => ['A', 'B', 'C', 'D', 'E']
};
};
const printFiles = (({fs, console, getFilePaths}) => {
return async function() {
const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'));
for(const file of files)
console.log(await file);
};
})(mock());
console.log(`Running at ${new Date() - start}`);
await printFiles();
console.log(`Finished running at ${new Date() - start}`);
})();
for ... of ...
작동 하는지 설명해 주 시겠습니까?