2

Node.js と Async コーディングは初めてです。Node.js で動作するネストされた for ループに相当するものを作成する必要があります。私の質問はここに投稿されたものと非常によく似ていることを理解しています: nodejs でネストされたループが非同期に行われ、次のループは 1 つが完了した後にのみ開始される必要がありますが、その投稿を詳細に見ても、コードを修正できませんでした。

XML フィードを使用しています。「パーサー」は xml2js パッケージを使用します。SQLクエリ(mysqlノードパッケージを使用している)を削除すると、ループは期待どおりに実行されますが、SQLクエリを入れると、すべての注文が最初に処理され、「DONE」が出力されます。その後、最後の注文のアイテムを繰り返し検索しようとするため、クエリは失敗します。

for ループを async.forEach ループに置き換えてみましたが、これは役に立ちませんでした。

ノードにとってより慣用的な方法でこれを再コーディングする方法についてのヘルプやアドバイスは大歓迎です。

どうもありがとう!シックスホビット

    parser.parseString(data, function (err, result) {
    if(err) throw(err);     
    var numOrders = result['Root']['Orders'][0]['Order'].length;
    var curr, currItem, currOrdId, items, sellersCode;
    console.log("Logging IDs of", numOrders, "orders");
    // for each order
    for (var j=0; j<numOrders; j++){
        //current order
        curr = result['Root']['Orders'][0]['Order'][j];         
        currOrdId = curr['OrderId'][0]          
        items = curr['Items'][0]['Item'];
        console.log("Order ID:", currOrdId, "--",items.length, "Items");
        // for each item
        for (var k=0; k<items.length; k++){
            currItem = items[k];
            sellersCode = currItem['SellersProductCode'][0];
            var sqlQuery = 'select data_index, fulltext_id, cataloginventory_stock_item.product_id from catalogsearch_fulltext inner join cataloginventory_stock_item where catalogsearch_fulltext.data_index like "' + sellersCode + '|%"' + 'and cataloginventory_stock_item.item_id = catalogsearch_fulltext.product_id';
            var query = connection.query(sqlQuery,function(err,rows,fields){
                if (err) throw(err);
                console.log("    Item ID          :",currItem['ItemId'][0]);
                console.log("    Full Text ID     :", rows[0]['fulltext_id']);
                console.log("    Product ID       :", rows[0]['product_id']);
            });
        }//for
    }//for
    console.log("DONE");
});//parseString
4

3 に答える 3

4

を使用することで、あなたは正しい軌道に乗っていましたasync.forEach。これを使用するためにこのコードを修正する方法は次のとおりです。

parser.parseString(data, function (err, result) {
    if(err) throw(err);
    var numOrders = result['Root']['Orders'][0]['Order'].length;
    var currOrdId, items, sellersCode;
    console.log("Logging IDs of", numOrders, "orders");
    // for each order
    async.forEach(result['Root']['Orders'][0]['Order'], function (curr, callback1) {
        currOrdId = curr['OrderId'][0];
        items = curr['Items'][0]['Item'];
        console.log("Order ID:", currOrdId, "--",items.length, "Items");
        async.forEach(items, function (currItem, callback2) {
            sellersCode = currItem['SellersProductCode'][0];
            var sqlQuery = 'select data_index, fulltext_id, cataloginventory_stock_item.product_id from catalogsearch_fulltext inner join cataloginventory_stock_item where catalogsearch_fulltext.data_index like "' + sellersCode + '|%"' + 'and cataloginventory_stock_item.item_id = catalogsearch_fulltext.product_id';
            var query = connection.query(sqlQuery,function(err,rows,fields){
                console.log("    Item ID          :",currItem['ItemId'][0]);
                console.log("    Full Text ID     :", rows[0]['fulltext_id']);
                console.log("    Product ID       :", rows[0]['product_id']);
                callback2(err);
            });
        }, callback1);
    }, function (err) {
        console.log("DONE");
    });
});//parseString

の各反復はasync.forEach、すべての非同期処理が完了したときにコールバック パラメータを呼び出す必要があります。この場合、2 つのレベルがあるため、頭の中で追跡するのが少し難しくなりますが、概念は同じです。

于 2012-12-10T17:34:32.650 に答える
1

これは古典的なループ内閉鎖問題です。currItem を引数として渡して、クロージャを解除する必要があります。

    for (var k=0; k<items.length; k++){
        currItem = items[k];
        sellersCode = currItem['SellersProductCode'][0];
        var sqlQuery = 'select data_index, fulltext_id, cataloginventory_stock_item.product_id from catalogsearch_fulltext inner join cataloginventory_stock_item where catalogsearch_fulltext.data_index like "' + sellersCode + '|%"' + 'and cataloginventory_stock_item.item_id = catalogsearch_fulltext.product_id';
        var query = connection.query(sqlQuery,(function(CI){
          return function(err,rows,fields){
            if (err) throw(err);
            console.log("    Item ID          :",CI['ItemId'][0]);
            console.log("    Full Text ID     :", rows[0]['fulltext_id']);
            console.log("    Product ID       :", rows[0]['product_id']);
          }
        })(currItem)); // Break closure by passing currItem as argument
    }//for
于 2012-12-10T17:35:57.317 に答える
0

これは古い投稿だと思いますが、この機能が役立つかもしれません

eachKVAsync = function(elements,userInfo,onKeyValue,ondone) {
    var onDone = ondone;
    var ret = null;
    var done=false;
    var isArray = typeof elements.forEach===$f$; 
    var keys   = isArray ? null     : [], 
        values = isArray ? elements : [];

    if (keys) {
        for (var k in elements) {
            keys.push(k);
            values.push(elements[k]);
        }
    }

    var aborted=false;
    var endLoop = function (userInfo){
        aborted=true;
        if (onDone) {
            onDone(userInfo,aborted);
            onDone = null;
        }
    }


    var i = 0;
    var iterate = function (userInfo) {
        if (i < values.length) {
            var ix=i;
            i++;
            onKeyValue((keys?keys[ix]:i),values[ix],userInfo,iterate,endLoop);          
        } else {
            if (onDone) {
                onDone(userInfo,aborted);
                onDone = null;
                return;
            }
        } 
    } 

    iterate(userInfo);

},

使用例

        eachKVAsync(
            elements, {
                aValue: 2004
            },
            function onItem(key, value, info, nextItem, endLoop) {
                if (value.isOk) {
                    info.aValue += value.total;
                    setTimeout(nextItem,1000,info);
                } else {
                    endLoop(info);
                }
            },
            function afterLastItem(info, loopEndedEarly) {
                if (!loopEndedEarly) {
                    console.log(info.aValue);
                }
            }
        );
于 2014-06-22T14:42:13.233 に答える