Jestem dość nowy z węzłem, a ja się uczymy i zajmowałem się async / obietnicami. W tej chwili staram się utworzyć proces, który tworzy wkładkę z DB (na przykład 10k rzędów), wywołuje usługę WebService, która przekształca jedną kolumnę, a następnie wprowadzić wkład dla zmodyfikowanych danych.

Więc robię zapytanie Oracle SQL i rezultat, robię foreach:

let counter = 0;
var binds = [];

res.rows.forEach((row) => {

    var original_data = row[0];

    Transform(original_data).then(new_data => {

        counter++;

        binds.push([original_data,new_data]);

        if (counter % 1000 === 0){
            console.log(`1K rows`);
            doInserts(binds);
            binds = [];
        }

    });

});

Dzwonię do doInserts co 1000 rzędów, więc nie mam wielu transakcji otwartych na Oracle.

Funkcja transformacji wywołuje usługę WebService, która rozwiązuje się z wartością, której potrzebuję.

function Transform(value){

    return new Promise(function(resolve, reject){
        var requestPath = `http://localhost:3000/transform/${value}`;
        var req = request.get(requestPath, function(err, response, body){
            if (!err && response.statusCode == 200){
                resolve(body);
            }else{
                reject("API didn't respond.");
            }
        }).end();
    });

}

Jednak jest to zatykanie WebService (używam Poproś o bibliotekę do podłączenia) Gdy foreach ma 10k wiersze . Myślę, że foreach nie robi transformacji w czasie synchronicznie.

Prawdopodobnie nie wiem, że nie wiedząc wielu węzła, asynchnika, obietnic .. ale jestem zdziwiony. Czy ktoś może pomóc?

0
Fede E. 1 czerwiec 2018, 19:42

3 odpowiedzi

Najlepsza odpowiedź

Robisz na wiele prośbę w tym samym czasie. Spróbuj ustawić zbieżność. Możesz użyć obietnicy Bluebirda PROMISE.MAP.HTML .

await Promise.map(rows, async (row) => {
    const new_data = await Transform(row[0])
    ...
}, {concurrency: 3})  // allow max 3 request at the same time
3
Xuezheng Ma 1 czerwiec 2018, 18:06

Możesz użyć dowolnej biblioteki obietnicy lub obietnicy ES6, aby zebrać szereg obietnic i rozwiązać je wszystkie razem.

W tym przykładzie użyję Bluebird

const Promise = require('bluebird');

async function resolvingManyPromises() {
    let counter = 0;
    let binds = [];
    let promiseArray = [];

    res.rows.forEach(row => {
        var original_data = row[0];

        promiseArray.push(Transform(original_data));
    });

    const resolvedPromises = await Promise.all(promiseArray);

    // Do something with the resolved values resolvedPromises
}

Należy pamiętać, że Promise.all spróbuje rozwiązać wszystkie obietnice w tablicy jednocześnie równolegle. Jeśli db ma limit liczenia połączenia, niektóre połączenia mogą się nie powieść.

0
Jason Kim 1 czerwiec 2018, 16:59

Wybrana odpowiedź odrzuca, jeśli jeden nie powiedzie się, a wszystkie sukcesy zostaną utracone (jeśli ostatnie odrzucenia straciłeś wszystko, ale ostatni wynik).

Jest to kod dostosowany do Twojej sytuacji Niewiele więcej informacji o kodzie można znaleźć Oto nie używa bluebird, ale używa lib .throttle (z lib, który zawiera ogólnie przydatne funkcje, które napisałem)

//lib comes from: https://github.com/amsterdamharu/lib/blob/master/src/index.js
const lib = require("lib");

const Fail = function(reason){this.reason=reason;};
const isFail = o=>(o&&o.constructor)===Fail;
const isNotFail = o=>!isFail(o);
const handleBatch = results =>{//this will handle results of a batch
  //failed are the requests that failed
  //you may want to save the ones that failed to file or something
  const failed = results.filter(isFail);
  const successes = results.filter(result=>!isFail(result));
  return doInserts(successes);
};
const processor = throttler => row =>
  throttler(//throttling Transform to max 10 active
    row=>
      Transform(row[0])
      .then(new_data =>[row[0],new_data])
    )(row)
    .catch(err=>new Fail([err,row]))//catch reject and resolve with fail object
;
//start the process
lib.batchProcess (handleBatch) (1000) (processor(lib.throttle(10))) ([]) (res.rows)
.then(
  results=>console.log("Process done")
  ,err=>console.error("This should not happen:".err)
);
0
HMR 1 czerwiec 2018, 21:52