2017-01-05 23 views
2

nodejs(6.9.1)で実行されているセイル(0.11.0)を使用しています。私はforループを通してそれを満たすことによって配列を構築しようとしています。私はこの完成したアレイをクライアントに応答して送るだろう。ここでは、スタックオーバーフローの人々によって示唆されているように私はforループを使ってnodejsの配列を構築する

議論herethis議論で

for (var i = yearStart; i < yearEnd+1; i++) { 
    arr.push(i); 
} 

を提案し、たとえば、様々な方法を試してみましたが、使用することが提案されています

var array = calendars.map(function(item) { 
    return item.id; 
}); 

console.log(array); 

同様に、私は多くのメソッドを試しましたが、同じ問題を抱えていますが、ループ中に配列がいっぱいになりますが、ループが完了するとすぐに、配列は非同期処理で空になります。したがって、スポンサー。私はループ本体内のインデックスをチェックしてみました、これに取り組むと

var userArray = []; 
_.each(users, function(user, index){ 
    MySQLConnector.query('CALL user_image (?)', [user.id], function(err, userImage){ 
    if(err){ 
     return res.json({"status":"some_error"}); 
    }else{ 
     userID = user.id 
     userImageID = userImage[0][0].id; 
     var userInfo = { 
     userID: userID, 
     userImageID: userImageID 
     } 
     userArray.push(userInfo) 
     if(index == users.length - 1){ 
      res.json({selectedUsers: userArray}); 
     } 
    } 
    }); 
}); 

をループ本体自体の内部からの応答を送信するには、私は空userArrayを開始し、その後ユーザーオブジェクトの各要素のを反復処理していますオブジェクトは、名前ユーザおよびインデックスによって特徴付けられる。 MySQLのクエリを通じて、私はuserImageオブジェクトを取得していますし、各反復では、私がユーザーIDuserImageIDで構成されていのUserInfoと呼ばれるオブジェクトを作成しています。私はuserArrayにこのオブジェクトをプッシュしています。そして、forループ(_.each)の繰り返しのたびに、最後のインデックスに達したかどうかをチェックします。最後のインデックスに達すると、ループ本体が完了する前に、最終配列が応答として送信されます。

ここでも私は配列本体が必ずしも完全に埋められないという問題があります。理由は、非同期プロセスによるものです。インデックスは必ずしも0,1,2,3,4、...の順番に従うとは限らず、任意の数で開始することができ、次の繰り返しで任意のインデックスにジャンプすることができます。たとえば、開始する最初のインデックスは4、2番目のインデックスは0、3番目のインデックスは2となります。このシーケンスは、ループのためにこれを実行するたびに異なります。ユーザーにとっては、ランダムなプロセスのように見えます。従ってusers.lengthは8であり、現在のインデックスをランダムに7第3の反復であり、条件index == users.length - 1が満たされると、誰かが示唆でき応答が3つの要素ではなく8

からなるアレイとだけ送信される場合私は、nodejsのforループを通して配列を塗りつぶし、その配列を応答として送信することにより、すべての項目が元の順序で配列に含まれるようにする、より強固な方法ですか?

+0

それは命令に従わないだろうと私はあなたもマップと同じ問題を抱えていると思う。ロダッシュとブルーバードの減量を見てください。後者では、注文を保証します。私はそれが同じであろうが、それについて間違っているかもしれないと思います。 –

+0

もう少し考えてみると、非同期ライブラリでは、私はしばしばeachSeriesを使用します。これは順序を保証し、既存のコードの解決策になるでしょう。 –

答えて

2

ノードjsを使用している場合は、bluebirdまたはasyncなどの約束ライブラリを使用して、非同期要求を処理する方が適切です。 ループが期待どおりに機能しないのは、非同期要求がループが待機していない_.eachの解決に時間がかかり、指摘した通りです。bluebirdを使用

は、それがdocumentaionから以下に説明するように動作Promise.map方法で行うことができる:(反復処理可能であるアレイ)

反復処理可能与えられ、又は約束を生成する反復処理可能、 の約束(または約束と値の組み合わせ)、Iterableのすべての値に対して を配列に反復し、指定されたマッパー関数を使用して配列を にマップします。

マッパー関数によって返された約束が待ち受けられており、 返された約束は、すべてのマップされた約束が も満たされるまで実行されません。配列内の約束が拒否された場合、またはマッパー関数によって返された 約束が拒否された場合、返された 約束も拒否されます。したがって

、あなたのコードは以下のように更新することができPromise.mapを使用する:

var Promise = require("bluebird");  

return Promise.map(users, function(user, index){ 
    return MySQLConnector.query('CALL user_image (?)', [user.id], function(err, userImage){ 
    if(err){ 
     return Promise.reject({"status":"some_error"}); 
    }else{ 
     userID = user.id 
     userImageID = userImage[0][0].id; 
     var userInfo = { 
     userID: userID, 
     userImageID: userImageID 
     } 
     return userInfo; 
    } 
    }); 
}) 
.then(function (usersArray){ 
    res.json({selectedUsers: usersArray}); 
}) 
.catch(function (err){ 
    res.json(err); 
}); 
+0

ありがとう、約束のライブラリを試してみよう。 – harshvardhan

+0

まだ応答配列が '[null、null、null、null、null、null]' – harshvardhan

+0

のようになっています。成功のコールバックに 'userInfo'を返す前にログを記録して一度だけチェックできますか? – superUser

1

あなたが同期SynJSを使用してコールバックを持つ関数でループを実行することができます。

var SynJS = require('synjs'); 
var mysql  = require('mysql'); 
var connection = mysql.createConnection({ 
    host  : 'localhost', 
    user  : 'tracker', 
    password : 'tracker123', 
    database : 'tracker' 
}); 


function myFunction1(modules,connection,users) { 
    var ret=[]; 
    for(var i=0; i<users.length; i++) { 
     connection.query("SELECT CONCAT('some image of user #',?) AS userImage", [users[i]], function(err, rows, fields) { 
       if (err) throw err; 

       ret.push({ 
        id: users[i], 
        image: rows[0].userImage 
       }); 
       modules.SynJS.resume(_synjsContext); // <-- indicate that callback is finished 
     }); 
     SynJS.wait(); // <-- wait for callback to finish 
    } 
    return ret; 
}; 

var modules = { 
     SynJS: SynJS, 
     mysql: mysql, 
}; 

var users = [1,5,7,9,20,21]; 

SynJS.run(myFunction1,null,modules,connection,users,function (ret) { 
    console.log('done. result is:'); 
    console.log(ret); 
}); 

結果は以下のようになります。

done. result is: 
[ { id: 1, image: 'some image of user #1' }, 
    { id: 5, image: 'some image of user #5' }, 
    { id: 7, image: 'some image of user #7' }, 
    { id: 9, image: 'some image of user #9' }, 
    { id: 20, image: 'some image of user #20' }, 
    { id: 21, image: 'some image of user #21' } ] 
関連する問題