2016-05-20 32 views
0

質問に対する非同期呼び出しの処理に少し苦労していますが、どのように適切な順序で応答を得ることができますか。私は、ユーザーの配列を持っているnode.jsのクエリでの非同期呼び出しの処理

が、それは私がユーザーや、電子メールなど、異なるテーブルでその詳細を挿入されて何をしたいのかJSONオブジェクトのペイロードを、持っている、などの写真は以下の私の擬似コードスニペットです

var jsonObj = {}; 
var jsonArray = []; 
for (var i = 0; i < userArray.length; i++) { 
    var userJSON = userArray[i]; 
    if (typeof userJSONJSON.list_of_emails != 'undefined') { 
     conn.query('insert into user_tble set ?', userJSON, function (err, ins) { 
      conn.query('insert into user_emails (user_id,email_address,) values ?', [globalEmailAddressArray], function (err, ins2) { 
       conn.query('insert into user_phones (user_id,phone_number) values ?', [globalPhoneNumberArray], function (err, ins3) { 
        conn.query('insert into user_pictures (user_id,pic_url) values ?', ['http://localhost:300/somepicture'], function (err, ins4) { 
         jsonObj["result"] = "executed1"; 
         jsonArray.push(jsonObj); 
         res.status(200).json(arr: jsonArray) 
        }) 
       }) 
      }) 
     }); 
    } else if (typeof userJSONJSON.list_of_phones != 'undefined') { 
     conn.query('insert into user_phones (user_id,phone_number) values ?', [globalPhoneNumberArray], function (err, ins3) { 
        conn.query('insert into user_pictures (user_id,pic_url) values ?', ['http://localhost:300/somepicture'], function (err, ins4) { 
         jsonObj["result"] = "executed2"; 
         jsonArray.push(jsonObj); 
         res.status(200).json(arr: jsonArray) 
        }) 
       }) 
    } 
} 

私はそれはそれは私に出力を返し などを返すJSONコードを実行する場合、私は

{ 
    "pay_load":[ 
     { 
      "list_of_emails": [ 
       {"email":"[email protected]"} 
       ], 
      "last_name": "", 
      "first_name": "User1" 

     }, 
    { 
     "list_of_email_addresses": [ 
      {"email":"[email protected]"} 
      ], 
     "last_name": "", 
     "first_name": "User2" 

    }, 
    { 
     "list_of_email_addresses": [], 
     "last_name": "", 
     "first_name": "User3" 

    } 
    ] 
} 

のようなペイロード何かを与える場合

{ 
arr:[ 
     { 
     result : "executed2" 
     } 
    ] 
} 

私は非同期の性質のために、私はそれが残りの2つをスキップすると思うようなものが欲しいです。

{ 
arr:[ 
     { 
     result : "executed1" 
     }, 
     { 
     result : "executed1" 
     }, 
     { 
     result : "executed2" 
     } 
    ] 
} 

要するに、上記の出力を達成するための非同期呼び出しをどのように処理できますか。

+0

[ループ内のJavaScriptのクロージャ - 単純な実施例]の可能な重複(http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example)用 – farhan3

答えて

1

私は個人的にプロミスを使用することをお勧めします。私はbluebirdで幸運を祈っています。そして、それはノードが変わることができるコールバック地獄を簡素化します。ただし、コールバックを使用する場合は、asyncライブラリを参照してください。

あなたが見ている問題は、コールバックを待たずにforループが次のアイテムに進むということです。 コールバックを待たずに終了します。各反復でクエリを実行し、クエリが終了した後にのみ処理を続行する必要があります。

さらに、最初の呼び出しで応答を送信するため、早期に返されます。あなたがここに非同期を使用した例です

(以下約束の例を参照)リスト全体が応答を送信し、その後人口とされるまで待ちたい:比較のために

var async = require("async") 

var userArray = ["mickey mouse", "donald duck", "goofy"]; 
async.eachSeries(userArray, function (user, cb) { 
    doFakeQuery('insert into user_tble set ?', function (err, ins) { 
      doFakeQuery('insert into user_emails (user_id,email_address,) values ?', function (err, ins2) { 
       doFakeQuery('insert into user_phones (user_id,phone_number) values ?', function (err, ins3) { 
        doFakeQuery('insert into user_pictures (user_id,pic_url) values ?', function (err, ins4) { 
         console.log("Finished queries for " + user) 
         cb(); 
        }) 
       }) 
      }) 
     }); 
}, function (err) { 
    console.log("Finished async.map") 
}) 

function doFakeQuery(query, callback) { 
    console.log("Running query '" + query + "'") 
    //Mock an asynchronous callback 
    setTimeout(function() { 
     callback(); 
    }, 300) 
} 

、ここにあなたのコードはに書き換えられ約束する。

var Promise = require("bluebird") 
//Convert conn.query into a function that returns a promise, instead of a callback 
var pQuery = Promise.promisify(conn.query) 

var jsonArray = [] 

Promise.mapSeries(userArray, function (user) { 
    if (user.list_of_emails != undefined) { 
     return addUser(user) 
      .then(addEmails) 
      .then(addPhones) 
      .then(addPictures) 
      .then(function() { 
       jsonArray.push({result: "executed1"}) 
      }) 
    } 
    else if (user.list_of_phones != undefined) { 
     return addPhones() 
      .then(addPictures) 
      .then(function() { 
       jsonArray.push({result: "executed2"}) 
      }) 
    } 
}) 
    .then(function() { 
     console.log("Done!") 
     res.status(200).json(jsonArray) 
    }) 

function addUser(userJSON) { 
    return pQuery('insert into user_tble set ?', userJSON) 
} 

function addEmails() { 
    return pQuery('insert into user_emails (user_id,email_address,) values ?', [globalEmailAddressArray]) 
} 

function addPhones() { 
    return pQuery('insert into user_phones (user_id,phone_number) values ?', [globalPhoneNumberArray]) 
} 

function addPictures() { 
    return pQuery('insert into user_pictures (user_id,pic_url) values ?', ['http://localhost:300/somepicture']) 
} 
+0

おかげなぜ、私たちはdoFakeQuery関数を使いたいのですか? –

+0

コールバック付きの関数を呼び出すことのみを目的としています。私は実行し、 'async.eachSeries'関数の出力を表示するコードを望みましたが、データベースへの接続は必要ありませんでした。あなたの終了コードはconn.query()を通常のように呼び出す必要があります。 – mdickin

+0

Promisesと** Edit **注記の新しい例に注意してください。 – mdickin

関連する問題