2017-06-20 18 views
0

setTimeoutを使用するように指示されていますが、foreachの完了後にはどうすればよいですか?ノードjs foreach done関数

app.post('/grid', function(req, res){ 
    getResults(req.body.idarray, function(callback){ 
     res.send(callback); 
    }); 
}); 
function getResults(userIds, callback) { 
    var totalresult = []; 
    userIds.forEach(function (user) { 
     sequence 
      .then(function (next) { 
       db.query('SELECT given FROM books WHERE user_id = ?', [user.userId], function (err2, result) { 
        if (err2) throw err2; 
        next(err, result); 
       }); 
      }) 
      .then(function (next, err, books) { 
       db.query('SELECT received FROM encycs WHERE user_id = ?', [user.userId], function (err3, result2) { 
        if (err3) throw err3; 
        next(err, result2, books); 
       }); 
      }) 
      .then(function (next, err, books, encycs) { 
       Calculation(books, encycs, function (cb) { 
        totalresult.push(cb); 
       }); 
       next(); 
      }); 
    }); 
    setTimeout(function() { 
     console.log(totalresult); // output ok. 
     return callback(totalresult); // returning as expected 
    }, 2000); 
} 

私はtotalresult.lengthとは何か分かりません。だから私は長さを確認することはできません。

+0

3番目の.then文に達していないか確認してください。そうでない場合は、チェックする必要があります。 – QuestionAndAnswer

+0

私は理解しませんでした。 .thenステートメントに到達する方法のミニサンプルを表示できますか? – user3325207

+0

あなたは3つの事例を持っています。 * books *を最初に選択し、* enycycs *を2番目に選択し、3番目のステートメントが何らかの計算を実行し、結果がtotalresult配列にプッシュされます。私が見る限りでは、これがあなたが住んでいる唯一の場所です。次にチェックするべきことは、コールバックの成功分岐のどこにでもtotalresult配列を返しているわけではなく、エラーのときだけです。実際に配列に値を設定するかどうかを確認してください。正しく表示されていれば返すわけではありませんので、必要なときにいつでも返すようにしてください。 – QuestionAndAnswer

答えて

1

あなたのユースケースによれば、何らかの理由でコールバックをコールしてtotalresultを渡す必要があります。なぜなら、ルート内のコードが外部コードであるためです。 これを行うには、3番目の.thenステートメントのnextを呼び出す前にコールバックを呼び出すことができます。それで

 ... 
     .then(function (next, err, books, encycs) { 
      Calculation(books, encycs, function (cb) { 
       totalresult.push(cb); 
      }); 
      callback(totalresult); 
      next(); 
      //console.log(totalresult); //output OK. 
     }); 

これは機能する場合があります。

アップデート1

あなたのコードに従うことは困難です。それの論理に追いつくことはできません。私はあなたに約束のアプローチを提案します。私はその解決法を用意しました。それはほとんどエラーを含んでいないかもしれませんが、あなたが達成しようとしていることの主なアイデアと、それがどのようにできるかを表しています。

app.post("/grid", (req, res) => { 
    getResults(req.body.idarray) 
     .then(data => { 
      res.status(200).json(data); 
     }) 
     .catch(err => { 
      console.error("Error occured", err); 
      res.status(500).json(err); 
     }); 
}); 

function getResults(userIds) { 
    let promises = userIds.map(loadCalculation); 
    //this will wait until all loadings are done 
    return Promise.all(promises); 
} 

function loadCalculation(user) { 
    //parallel loading of the books and encycs 
    return Promise.all([loadBooks(user), loadEncycs(user)]) 
     .then(results => { 
      let books = results[0]; 
      let encycs = results[1]; 

      let totalresult = []; 

      Calculation(books, encycs, function (cb) { 
       totalresult.push(cb); 
      }); 

      return totalresult; 
     }); 
} 

function loadBooks(user) { 
    return makeQuery('SELECT given FROM books WHERE user_id = ?', user); 
} 

function loadEncycs(user) { 
    return makeQuery('SELECT received FROM encycs WHERE user_id = ?', user); 
} 

function makeQuery(query, user) { 
    return Promise((resolve, reject) => { 
     db.query(query, [user.userId], function (err, result) { 
      if(err) { 
       reject(err); 
      } else { 
       resolve(result); 
      } 
     });   
    }); 
} 

してください、ので、少なくとも、私は単一のクエリですべての書籍やencycsをロードする可能性は、あなたがそこにあることを確信している、これは実際にデータベースからデータをロードするパフォーマンスの方法ではありませんのでご注意あなたはSQLを使用しており、それは本当に柔軟な言語です。

+0

それは仕事をしていないと "送信された後にヘッダーを設定できません"。あなたがまだループしていると言っている場所に戻ってください。したがって、コールバックをもう一度呼び出すことになります。 – user3325207

+0

async.eachは何も返しません。最初から始めましょう。なぜあなたはシーケンスとasync.eachを使用していますか?なぜ彼らの連鎖を約束しないのですか?それとも、非同期でもES6/7の構文を待っていますか?そのようなコードを理解することは難しいです。 – QuestionAndAnswer

+0

私は約束の経験はなく、例は私にとっては理解しにくいです。私は私の質問を変えた。あなたはそれをもう一度見ることができますか?ありがとう – user3325207

関連する問題