javascript async란 promise - forEach 루프와 함께 async / await 사용





6 Answers

ES2018을 사용하면 위의 모든 답변을 크게 단순화 할 수 있습니다.

async function printFiles () {
  const files = await getFilePaths()

  for await (const file of fs.readFile(file, 'utf8')) {
    console.log(contents)
  }
}

사양보기 : https://github.com/tc39/proposal-async-iteration

2018-09-10 :이 답변은 최근 많이 주목 받고 있습니다. 비동기식 반복에 대한 자세한 내용은 Axel Rauschmayer의 블로그 게시물을 참조하십시오. http://2ality.com/2016/10/asynchronous-iteration.html

all 순서 axios

forEach 루프에서 async/await 을 사용하는 데 문제가 있습니까? 나는 파일의 배열을 통해 반복하고 각 파일의 내용을 await 있어요.

import fs from 'fs-promise'

async function printFiles () {
  const files = await getFilePaths() // Assume this works fine

  files.forEach(async (file) => {
    const contents = await fs.readFile(file, 'utf8')
    console.log(contents)
  })
}

printFiles()

이 코드는 작동하지만이 문제가 발생할 수 있습니까? 누군가 당신에게 async/await higher를 사용하도록되어 있지 않다는 것을 말해주었습니다. 그래서 이와 같은 문제가 있는지 묻고 싶었습니다.




Promise.all 대신 Array.prototype.map ( Promise 가 해결되는 순서를 보장하지 않음)과 함께 Array.prototype.map 사용하여 해결 된 Promise 시작합니다.

async function printFiles () {
  const files = await getFilePaths();

  await files.reduce(async (promise, file) => {
    // This line will wait for the last async function to finish.
    // The first iteration uses an already resolved Promise
    // so, it will immediately continue.
    await promise;
    const contents = await fs.readFile(file, 'utf8')
    console.log(contents)
  }, Promise.resolve());
}



위의 두 가지 솔루션 모두 작동하지만 안토니오는 적은 코드로 작업을 수행합니다. 데이터베이스에서 데이터를 확인하는 방법, 여러 가지 다른 하위 참조에서 배열을 푸는 것, 그리고 결국에는 약속대로 해결하는 것입니다. 끝난:

Promise.all(PacksList.map((pack)=>{
    return fireBaseRef.child(pack.folderPath).once('value',(snap)=>{
        snap.forEach( childSnap => {
            const file = childSnap.val()
            file.id = childSnap.key;
            allItems.push( file )
        })
    })
})).then(()=>store.dispatch( actions.allMockupItems(allItems)))



Task, futurize 및 Traversable List를 사용하면 간단하게 할 수 있습니다.

async function printFiles() {
  const files = await getFiles();

  List(files).traverse( Task.of, f => readFile( f, 'utf-8'))
    .fork( console.error, console.log)
}

이걸 어떻게 세우는거야.

import fs from 'fs';
import { futurize } from 'futurize';
import Task from 'data.task';
import { List } from 'immutable-ext';

const future = futurizeP(Task)
const readFile = future(fs.readFile)

원하는 코드를 구조화하는 또 다른 방법은

const printFiles = files => 
  List(files).traverse( Task.of, fn => readFile( fn, 'utf-8'))
    .fork( console.error, console.log)

아니면 아마도 더 기능 지향적 인

// 90% of encodings are utf-8, making that use case super easy is prudent

// handy-library.js
export const readFile = f =>
  future(fs.readFile)( f, 'utf-8' )

export const arrayToTaskList = list => taskFn => 
  List(files).traverse( Task.of, taskFn ) 

export const readFiles = files =>
  arrayToTaskList( files, readFile )

export const printFiles = files => 
  readFiles(files).fork( console.error, console.log)

그런 다음 부모 함수에서

async function main() {
  /* awesome code with side-effects before */
  printFiles( await getFiles() );
  /* awesome code with side-effects after */
}

인코딩에 더 많은 유연성을 원한다면이 작업을 수행 할 수 있습니다 (재미 있기 때문에 제안 된 파이프 전달 연산자를 사용하고 있습니다)

import { curry, flip } from 'ramda'

export const readFile = fs.readFile 
  |> future,
  |> curry,
  |> flip

export const readFileUtf8 = readFile('utf-8')

추신 : 나는 콘솔에서이 코드를 시도하지 않았고 몇 가지 오타가있을 수 있습니다 ... "돔 꼭대기에서 직선 프리 스타일!" 90 년대 아이들이 말할 것입니다. :-피




중요한 주의 사항 은 다음과 같습니다. await + for .. of 메소드와 forEach + async way는 실제로 다른 효과를 나타냅니다.

실제 for 루프를 기다리면 모든 비동기 호출이 하나씩 실행되는지 확인할 수 있습니다. 그리고 forEach + async 방법은 동시에 모든 약속을 해고합니다. DB 질의를하거나 볼륨 제한이있는 웹 서비스를 방문 하고 한 번에 100,000 건의 전화를 끊지 않으려는 경우 에는 더 빠르지 만 때때로 압도 됩니다 .

async/await 사용하지 않고 파일이 차례로 읽히는 지 확인하려면 reduce + promise (덜 우아함)를 사용할 수도 있습니다.

files.reduce((lastPromise, file) => 
 lastPromise.then(() => 
   fs.readFile(file, 'utf8')
 ), Promise.resolve()
)

또는 forEachAsync를 만들어 루프를 만들 때 기본적으로 사용할 수 있습니다.

Array.prototype.forEachAsync = async function(cb){
    for(let x of this){
        await cb(x);
    }
}



나는 잘 테스트 된 (주당 수백만 다운로드) pifyasync 모듈을 사용할 것이다. 비동기 모듈에 익숙하지 않다면 문서 를 체크 아웃 하는 것이 좋습니다. 비싼 비동기 메서드를 사용하면 코드를 단순화 할 때 여러 개발자가 메서드를 재생성하는 데 시간을 낭비하거나 악화 될 수 있으므로 비동기 코드를 유지하기가 어렵습니다.

const async = require('async')
const fs = require('fs-promise')
const pify = require('pify')

async function getFilePaths() {
    return Promise.resolve([
        './package.json',
        './package-lock.json',
    ]);
}

async function printFiles () {
  const files = await getFilePaths()

  await pify(async.eachSeries)(files, async (file) => {  // <-- run in series
  // await pify(async.each)(files, async (file) => {  // <-- run in parallel
    const contents = await fs.readFile(file, 'utf8')
    console.log(contents)
  })
  console.log('HAMBONE')
}

printFiles().then(() => {
    console.log('HAMBUNNY')
})
// ORDER OF LOGS:
// package.json contents
// package-lock.json contents
// HAMBONE
// HAMBUNNY
```




Related