2017-06-20 87 views
0

使用setTimeout,我應該在foreach完成後使用什麼?節點js foreach功能

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

檢查你是否達到第三。然後聲明。如果沒有,那麼你需要檢查它。 – QuestionAndAnswer

+0

我不明白。你能舉一個小例子來說明如何達成一個.then聲明嗎? – user3325207

+0

你有三個案例。首先選擇* books *,然後選擇* enycycs *,第三個語句執行一些計算並將結果推送到totalresult數組中。據我所知,這是你填充它的唯一地方。第二件事情要檢查,你沒有在回調的成功分支中的任何地方返回你的totalresult數組,只有在出錯時。所以,檢查你是否真的填充數組,如果我看到正確的你沒有返回它,因此,只要你需要返回它。 – QuestionAndAnswer

回答

1

因此,根據您的使用情況,您需要以某種方式調用回調函數並將totalresult傳遞給它,因爲那是您的外部代碼,代碼路徑中的代碼。 要做到這一點,您可以在調用第三個.then語句的下一個之前調用回調函數。像那樣。

 ... 
     .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

它沒有工作,並拋出「發送後無法設置標題。」。因爲你說的地方還在循環中。所以,它會一次又一次地調用回調,直到asyc.each完成。 – user3325207

+0

async.each不會返回任何內容。我們從頭開始。爲什麼使用sequence和async.each?爲什麼不與他們的鏈接承諾?甚至是異步等待ES6/7的語法?很難理解這樣的代碼。 – QuestionAndAnswer

+0

我沒有承諾的經驗,例子對我來說很難理解。我改變了我的問題。你能再看一遍嗎?謝謝 – user3325207