programing

Node.js 네이티브 Promise입니다.병렬 또는 순차적으로 모든 처리를 수행합니까?

randomtip 2023. 2. 4. 08:32
반응형

Node.js 네이티브 Promise입니다.병렬 또는 순차적으로 모든 처리를 수행합니까?

점에 대해서는 문서상 명확하지 않기 때문에 명확히 하고 싶습니다.

질문 1: 현재Promise.all(iterable)모든 약속을 순차적으로 또는 병렬로 처리할 수 있습니까? 구체적으로 '', '연쇄약속', '', '연쇄약속', '연쇄약속', '연쇄약속', '연쇄약속', '연쇄약속', '연쇄약속', '연쇄약속', '연쇄약속', '연쇄약속약속약속약속약속약속'과

p1.then(p2).then(p3).then(p4).then(p5)....

다른 요?p1,p2,p3,p4,p5 되어 (의 거부되면 바로 결과가 됩니다.

질문 2: 만약Promise.all병렬로 실행할 수 있습니다.순차적으로 실행할 수 있는 편리한 방법이 있습니까?

주의: Q 또는 Bluebird는 사용하지 않고 ES6의 네이티브 사양을 모두 사용합니다.

이는?Promise.all(iterable)든든약 속행 ?? ????

아니요, 약속은 "실행"할 수 없습니다.작성 작업을 시작합니다.결과만 표시됩니다.이러한 작업은 다음 사용자에게 전달하기 전에 모든 작업을 동시에 수행합니다.Promise.all.

Promise.all여러 가지 약속만 기다리고 있습니다.어떤 순서로 해결하는지, 또는 병렬로 계산되는지 여부는 중요하지 않습니다.

연속적으로 반복할 수 있는 편리한 방법이 있습니까?

어쩔 수 Promise.all([p1, p2, p3, …])(어느 쪽인가 하면)그러나 비동기 함수를 반복할 수 있는 경우에는 실제로 순차적으로 실행할 수 있습니다.으로는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

[fn1, fn2, fn3, …]

로.

fn1().then(fn2).then(fn3).then(…)

이를 위한 솔루션은 다음과 같습니다.

iterable.reduce((p, fn) => p.then(fn), Promise.resolve())

병렬로

await Promise.all(items.map(async (item) => { 
  await fetchItem(item) 
}))

장점:빠른.나중에 장애가 발생하더라도 모든 반복이 시작됩니다.단, "빠른 장애"가 발생합니다.에러 발생시에도 모든 반복을 병행하여 완료하려면 를 사용합니다.기술적으로는 병렬이 아닌 동시 호출입니다.

순서대로

for (const item of items) {
  await fetchItem(item)
}

장점:루프 내의 변수는 반복마다 공유할 수 있습니다.일반적인 필수 동기 코드처럼 동작합니다.

NodeJS는 단일 스레드 이벤트 루프 아키텍처이므로 약속을 병렬로 실행하지 않습니다.다중 코어 CPU를 활용하기 위해 새로운 자식 프로세스를 생성하여 병렬로 실행할 수 있습니다.

병렬과 구성

뭐, ㅇㅇ, ㅇㅇㅇ?Promise.all적, , 2, 2, 2, ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), with, with, with, with, with, with, with, with, with, with, with, with, with, with, with, with, with, with, with, with, , with, with, with, with, with, 그 모든 약속들이 결과를 낳았어요.합니다.당신이 직접 거절을 관리하지 않는 한, 모든 것이 실패한 첫 번째 약속에 실패할 것이다.

병렬과 동시 사이에는 큰 차이가 있다.첫 번째 계산은 다른 프로세스에서 정확히 동시에 실행되며, 그들은 리듬에 따라 진행되며, 다른 계산은 이전 계산이 종료되고 Sam에서 진행되기를 기다리지 않고 차례로 다른 계산을 실행한다.서로 의지하지 않는 시간.

으로, 질문의 답변은 다음과 같습니다.Promise.all이치노

버지의 대답은 를 올바른 길로 이끌었고Array.reduce.

그러나 실제로 실행 약속을 차례로 반환하는 함수를 얻기 위해서는 몇 가지 네스팅을 추가해야 했습니다.

다운스트림 제한으로 인해 순차적으로 전송해야 하는 파일 배열이 실제 사용 사례입니다.

결론은 다음과 같습니다.

getAllFiles().then( (files) => {
    return files.reduce((p, theFile) => {
        return p.then(() => {
            return transferFile(theFile); //function returns a promise
        });
    }, Promise.resolve()).then(()=>{
        console.log("All files transferred");
    });
}).catch((error)=>{
    console.log(error);
});

이전 답변에서 알 수 있듯이 다음을 사용합니다.

getAllFiles().then( (files) => {
    return files.reduce((p, theFile) => {
        return p.then(transferFile(theFile));
    }, Promise.resolve()).then(()=>{
        console.log("All files transferred");
    });
}).catch((error)=>{
    console.log(error);
});

다른 파일 전송을 시작하기 전에 전송이 완료될 때까지 기다리지 않았습니다.또한 첫 번째 파일 전송이 시작되기 전에 "All files transfered" 텍스트가 표시되었습니다.

내가 뭘 잘못했는지 모르겠지만 나한테 효과가 있었던 걸 공유하고 싶었어

편집: 이 글을 썼기 때문에 첫 번째 버전이 작동하지 않은 이유를 알 수 있습니다. then()약속을 반환하는 함수를 기대합니다.그래서 괄호 없이 함수명을 통과시켜야 합니다!이제 내 함수는 인수를 원하기 때문에 인수를 사용하지 않고 익명 함수로 마무리해야 합니다.

재귀 함수를 사용하여 비동기 함수를 사용하여 반복 가능한 함수를 순차적으로 처리할 수도 있습니다.를 들어, 배열 " " " 가 되면 " " " 가 지정됩니다.a someAsyncFunction()

var a = [1, 2, 3, 4, 5, 6]

function someAsyncFunction(n) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("someAsyncFunction: ", n)
      resolve(n)
    }, Math.random() * 1500)
  })
}

//You can run each array sequentially with: 

function sequential(arr, index = 0) {
  if (index >= arr.length) return Promise.resolve()
  return someAsyncFunction(arr[index])
    .then(r => {
      console.log("got value: ", r)
      return sequential(arr, index + 1)
    })
}

sequential(a).then(() => console.log("done"))

@Bergi답변 대해 자세히 설명하자면(매우 간결하지만 이해하기 어렵다.

이 코드는 어레이 내의 각 항목을 실행하고 끝에 다음 '그 후 체인'을 추가합니다.

function eachorder(prev,order) {
        return prev.then(function() {
          return get_order(order)
            .then(check_order)
            .then(update_order);
        });
    }
orderArray.reduce(eachorder,Promise.resolve());

비동기식 wait를 사용하면 일련의 약속을 쉽게 순차적으로 실행할 수 있습니다.

let a = [promise1, promise2, promise3];

async function func() {
  for(let i=0; i<a.length; i++){
    await a[i]();
  }  
}

func();

주의: 위의 구현에서는 약속이 거부되면 나머지는 실행되지 않습니다., 의 약속을 하세요.await a[i]();에 inside inside inside try catch

평행한

이 예를 참조해 주세요.

const resolveAfterTimeout = async i => {
  return new Promise(resolve => {
    console.log("CALLED");
    setTimeout(() => {
      resolve("RESOLVED", i);
    }, 5000);
  });
};

const call = async () => {
  const res = await Promise.all([
    resolveAfterTimeout(1),
    resolveAfterTimeout(2),
    resolveAfterTimeout(3),
    resolveAfterTimeout(4),
    resolveAfterTimeout(5),
    resolveAfterTimeout(6)
  ]);
  console.log({ res });
};

call();

코드를 실행하면 6개의 약속 모두에 대해 "CALLED" 콘솔이 실행되며, 해결되면 타임아웃 후 6개의 응답마다 콘솔이 동시에 실행됩니다.

노드의 문제를 해결하려고 하다가 우연히 이 페이지를 발견했습니다.JS: 파일 청크를 재구성합니다.기본적으로:파일명의 배열이 있습니다.하나의 큰 파일을 작성하려면 모든 파일을 올바른 순서로 추가해야 합니다.이거 비동기적으로 해야 돼요.

'fs'를 합니다.appendFileSync이 작업 중에는 서버를 차단하고 싶지 않았습니다.는 ★★★★★★★★★★★★★★★fs.promises이 물건들을 묶을 방법을 찾아야 합니다.두조작이 했기 때문에 가 없었다.fsPromises.read()청크를 또, 「」를 참조해 주세요.fsPromises.appendFile()대상 파일에 대응합니다.JavaScript를 더 잘 사용했다면 이전 답변이 도움이 되었을지도 모릅니다.;-)

우연히 이것을 발견해, 제대로 된 솔루션을 해킹할 수 있었습니다.

/**
 * sequentially append a list of files into a specified destination file
 */
exports.append_files = function (destinationFile, arrayOfFilenames) {
    return arrayOfFilenames.reduce((previousPromise, currentFile) => {
        return previousPromise.then(() => {
            return fsPromises.readFile(currentFile).then(fileContents => {
                return fsPromises.appendFile(destinationFile, fileContents);
            });
        });
    }, Promise.resolve());
};

그리고 여기 재스민 유닛 테스트가 있습니다.

const fsPromises = require('fs').promises;
const fsUtils = require( ... );
const TEMPDIR = 'temp';

describe("test append_files", function() {
    it('append_files should work', async function(done) {
        try {
            // setup: create some files
            await fsPromises.mkdir(TEMPDIR);
            await fsPromises.writeFile(path.join(TEMPDIR, '1'), 'one');
            await fsPromises.writeFile(path.join(TEMPDIR, '2'), 'two');
            await fsPromises.writeFile(path.join(TEMPDIR, '3'), 'three');
            await fsPromises.writeFile(path.join(TEMPDIR, '4'), 'four');
            await fsPromises.writeFile(path.join(TEMPDIR, '5'), 'five');

            const filenameArray = [];
            for (var i=1; i < 6; i++) {
                filenameArray.push(path.join(TEMPDIR, i.toString()));
            }

            const DESTFILE = path.join(TEMPDIR, 'final');
            await fsUtils.append_files(DESTFILE, filenameArray);

            // confirm "final" file exists    
            const fsStat = await fsPromises.stat(DESTFILE);
            expect(fsStat.isFile()).toBeTruthy();

            // confirm content of the "final" file
            const expectedContent = new Buffer('onetwothreefourfive', 'utf8');
            var fileContents = await fsPromises.readFile(DESTFILE);
            expect(fileContents).toEqual(expectedContent);

            done();
        }
        catch (err) {
            fail(err);
        }
        finally {
        }
    });
});

for 루프에 의해 실행할 수 있습니다.

비동기 함수 반환 약속:

async function createClient(client) {
    return await Client.create(client);
}

let clients = [client1, client2, client3];

다음 코드를 쓰면 클라이언트가 병렬로 생성됩니다.

const createdClientsArray = yield Promise.all(clients.map((client) =>
    createClient(client);
));

단, 클라이언트를 순차적으로 작성하려면 다음 루프를 사용해야 합니다.

const createdClientsArray = [];
for(let i = 0; i < clients.length; i++) {
    const createdClient = yield createClient(clients[i]);
    createdClientsArray.push(createdClient);
}

순차적인 약속을 해결하기 위해 for를 사용해 왔습니다.도움이 될지는 모르겠지만 이게 제가 하고 있는 일이에요.

async function run() {
    for (let val of arr) {
        const res = await someQuery(val)
        console.log(val)
    }
}

run().then().catch()

버지대답이 통화를 동기화하는 데 도움이 되었다.이전 함수를 호출한 후 각 함수를 호출하는 예를 아래에 추가했습니다.

function func1 (param1) {
    console.log("function1 : " + param1);
}
function func2 () {
    console.log("function2");
}
function func3 (param2, param3) {
    console.log("function3 : " + param2 + ", " + param3);
}

function func4 (param4) {
    console.log("function4 : " + param4);
}
param4 = "Kate";

//adding 3 functions to array

a=[
    ()=>func1("Hi"),
    ()=>func2(),
    ()=>func3("Lindsay",param4)
  ];

//adding 4th function

a.push(()=>func4("dad"));

//below does func1().then(func2).then(func3).then(func4)

a.reduce((p, fn) => p.then(fn), Promise.resolve());

예, 다음과 같이 일련의 약속 반환 함수를 연결할 수 있습니다(이것에 의해 각 함수의 결과가 다음 함수로 넘어갑니다.물론 동일한 인수를 각 함수에 전달하도록 편집할 수도 있습니다(또는 인수를 전달하지 않음).

function tester1(a) {
  return new Promise(function(done) {
    setTimeout(function() {
      done(a + 1);
    }, 1000);
  })
}

function tester2(a) {
  return new Promise(function(done) {
    setTimeout(function() {
      done(a * 5);
    }, 1000);
  })
}

function promise_chain(args, list, results) {

  return new Promise(function(done, errs) {
    var fn = list.shift();
    if (results === undefined) results = [];
    if (typeof fn === 'function') {
      fn(args).then(function(result) {
        results.push(result);
        console.log(result);
        promise_chain(result, list, results).then(done);
      }, errs);
    } else {
      done(results);
    }

  });
}

promise_chain(0, [tester1, tester2, tester1, tester2, tester2]).then(console.log.bind(console), console.error.bind(console));

이 샘플 참조

약속해.모두 병렬로 동작하고 있다

const { range, random, forEach, delay} = require("lodash");  
const run = id => {
    console.log(`Start Task ${id}`);
    let prom = new Promise((resolve, reject) => {
        delay(() => {
            console.log(`Finish Task ${id}`);
            resolve(id);
        }, random(2000, 15000));
    });
    return prom;
}


const exec = () => {
    let proms = []; 
    forEach(range(1,10), (id,index) => {
        proms.push(run(id));
    });
    let allPromis = Promise.all(proms); 
    allPromis.then(
        res => { 
            forEach(res, v => console.log(v));
        }
    );
}

exec();

언급URL : https://stackoverflow.com/questions/30823653/is-node-js-native-promise-all-processing-in-parallel-or-sequentially

반응형