2017-06-28 43 views
0

這是我在我的index.js中的一些代碼。它等待該用戶訪問url.com/proxy,然後加載我的代理頁面,這實際上只是一個發送電子郵件和代碼的表單。從我的MongoDB數據庫中,我使用代碼獲取用戶訂單,其中包含我需要的一些信息(如產品和他們試圖獲得的消息)。出於某種原因,它在收到此信息之前似乎已經做出了迴應,然後在下次提交表單時持有該信息。res.send()不發送當前響應,而是保留最後一個

我res.send換行符(產品+「\ n」 +消息)心不是任何工作,但現在那不是什麼大不了的事。

但是...例如,我第一次填寫表格生病得到一個空白的響應。第二次,我會收到我填寫的第一份表格的回覆,然後第三次得到第二份回覆。我對Web開發相當陌生,感覺我正在做一些明顯錯誤的事情,但似乎無法弄清楚。任何幫助將不勝感激,謝謝。

app.get('/proxy', function(req,res){ 
     res.sendFile(__dirname+ "/views/proxy.html"); 
    }); 

    var message = ""; 
    var product = ""; 

    app.post('/getMessage', function(req,res) 
    { 
     returnMsg(req.body.user.code, req.body.user.email); 
     //res.setHeader('Content-Type', 'text/plain'); 
     res.send(product + "\n" + message); 
    }); 

    function returnMsg(code, email){ 
     MongoClient.connect(url, function(err, db){ 
      var cursor = db.collection('Orders').find({ "order_id" : Number(code) }) 
      cursor.each(function(err, doc){ 
       assert.equal(err, null); 
       if (doc!= null) 
       { 
         message = doc["message"]; 
         product = doc["product"]; 
       } 
       else { 
         console.log("wtf"); 
        // error code here 
       } 
      }); 
      console.log(email + " + " + message); 
      var document = { 
        "Email" : email, 
        "Message" : message 
      } 
      db.collection("Users").insertOne(document); 
      db.close(); 
     }); 
    } 
+0

這不是nodejs的工作方式。如果db操作結束,您必須傳遞給returnMsg()一個回調函數來執行。你正在嘗試在節點中進行同步編程,而這是一個異步的環境。看到這個示例以及如何使用回調函數:https://gist.github.com/fwielstra/1025038 – Oscar

回答

1

您需要做大量關於node.js中的異步編程工作的閱讀。此代碼存在重大設計問題:

  1. 您正在使用模塊級變量而不是請求級變量。
  2. 您沒有正確處理異步響應。

所有這些都使,根本無法正常工作的服務器。你已經發現了其中一個問題。您的異步響應在您發送響應後完成,因此您最終將發送之前保存的響應而不是當前的響應。另外,如果多個用戶正在使用您的服務器,他們的響應會彼此拉攏。

這裏的核心設計原則是:第一,你需要學習如何使用異步操作編程。任何使用異步響應的函數都想要將該值返回給調用者,需要接受回調並通過回調傳遞異步值或返回承諾並通過已解決的承諾返回值。然後調用者需要使用該回調或承諾在可用時獲取異步值,然後才發送響應。

此外,與請求相關聯的所有數據需要保持「內部」的要求,辦理或請求對象 - 在沒有任何模塊級或全局變量。這樣可以防止一個用戶的請求干擾另一個用戶的請求。

要了解如何從功能方面與它的異步操作返回一個值,看How do I return the response from an asynchronous call?


什麼結束了在代碼中發生的事情是這個序列的事件:

  1. /getMessage
  2. 傳入的請求,你叫returnMsg()
  3. returnMsg啓動與數據庫的連接,然後返回
  4. 您的請求處理程序會調用res.send()以前的messageproduct變量。
  5. 然後,稍後的某個時間,數據庫連接完成,並且您調用db.collection().find(),然後重複cursor
    6一段時間後,光標迭代具有第一個結果,您將其放入messageproduct變量(其中這些值將一直保持到下一個請求進入)。

在研究你的代碼應該如何工作的時候,有一些關於你的邏輯的問題還不清楚。您正在cursor.each()的內部指定messageproduct。由於cursor.each()是一個可以運行多次迭代的循環,您實際上想要在res.send()中使用哪個值messageproduct


假設你想從你cursor.each()循環的最後messageproduct值,你可以這樣做:

app.post('/getMessage', function(req, res) { 
    returnMsg(req.body.user.code, req.body.user.email, function(err, message, product) { 
     if (err) { 
      // send some meaningful error response 
      res.status(500).end(); 
     } else { 
      res.send(product + "\n" + message); 
     } 
    }); 
}); 

function returnMsg(code, email, callback) { 
    let callbackCalled = false; 
    MongoClient.connect(url, function(err, db) { 
     if (err) { 
      return callback(err); 
     } 
     var cursor = db.collection('Orders').find({ 
      "order_id": Number(code) 
     }); 
     var message = ""; 
     var product = ""; 

     cursor.each(function(err, doc) { 
      if (err) { 
       if (!callbackCalled) { 
        callback(err); 
        callbackCalled = true; 
       } 
      } else { 
       if (doc != null) { 
        message = doc["message"]; 
        product = doc["product"]; 
       } else { 
        console.log("wtf"); 
        // error code here 
       } 
      } 
     }); 
     if (message) { 
      console.log(email + " + " + message); 
      var document = { 
       "Email": email, 
       "Message": message 
      } 
      db.collection("Users").insertOne(document); 
     } 
     db.close(); 
     if (!callbackCalled) { 
      callback(null, message, product); 
     } 
    }); 
} 

就個人而言,我會使用的承諾和使用承諾的界面在你的數據庫,而不是回調。


該代碼仍然只是概念上的,因爲它有您需要處理,如其他問題:

  1. 正確的錯誤處理在很大程度上仍然沒有完成。
  2. 在繼續操作之前,您並不是真的在等待insert.One()這樣的事情完成。
+0

我只希望遊標只有一個答案,但cursor.each似乎是達到它的方式,也許是錯了。我正在閱讀你給我的鏈接,並檢查你現在的答案,我很感激。 – moardee

+0

@moardee - 我在我的答案中添加了一個概念代碼示例。 – jfriend00

相關問題