2017-10-21 41 views
0

下面的代碼應該把一個字符串作爲一個輸入(這裏是inMessage)並且將它分開。然後,它向Firebase實時數據庫查詢關聯的鍵和值,並用檢索到的值替換該單詞。這個修改後的字符串必須作爲輸出返回。如何連接數組對象和字符串以獲取Javascript中的字符串?

現在,我似乎無法找到一種方法來使'味精'一個正確的字符串。如果我硬編碼一個字符串,而不是味精,我得到輸出正確呈現。那麼如何讓msg成爲一個合適的字符串呢? (我已經試過「」的toString(),字符串()和JSON.stringify()括起來 - 必須有我丟失的東西在這裏)

function queryDB(senderID, inMessage){ 
    var arr=inMessage.split(" "); 
    console.log(arr); 
    var i; 
    console.log('inside queryDB'); 
    var msg=""; 
    for(i=0;i<arr.length;i++){ 
    var x = 'https://oreo-fd681.firebaseio.com/'+arr[i]+'.json'; 
    request({ 
     url: x, 
     method: 'GET' 
     }, function(error, response, body) { 
      console.log(response.body); 
      if (error) { 
       console.log('Error making api call ' + error); 
      } else if (response.body.error){ 
       console.log('Error making api call' + response.body.error); 
      } 
      else if(response==null) { 
       //if not found in DB concatenate whatever arr[i] holds 
       callback1(); 
      } 
      else { 
       //else concatenate the found key 
       var n=JSON.parse(response.body); 
       //remove the quotes associated with key value 
       callback2(JSON.stringify(n.key).replace(/['"]+/g, '')); 
      } 
     }); 
     function callback1(){ 
     msg+=(arr[i]); 
     msg+=" "; 
     console.log(msg); 
     } 
     function callback2(add){ 
     msg+=(add); 
     msg+=" "; 
     console.log(msg); 
     } 
    } 
     //add quotes back - not sure of this 
     sendMessageToUser(senderID, ("\""+msg+"\"")); 
    } 

回答

0

你的問題與request回調的異步性質有關:

  • 您執行sendMessageToUser任何請求的返回結果之前。
  • 因爲ivar宣佈,爲i價值將會達到arr.length任何請求的返回結果之前,所以在callback1該值將是無用的 - 它總是會引用arr[arr.length],這是不確定的
  • 假設返回的鍵是字符串,沒有理由先將它們字符串化爲JSON,然後刪除引號。事實上,如果一個關鍵字包含引號,那麼這些將會在這個過程中丟失。
  • 無法保證對請求的回覆將以相同的順序返回。這樣做msg +=可能會生成具有錯誤順序的鍵的字符串。
  • 不是一個bug,但是在一個循環中創建函數應該保持最小。所以我不會像這樣使用callback1callback2

下面是一種方法,它堅持普通的舊回調模式。它有這些變化:

  • 它首先收集數組中的密鑰,以便您可以將密鑰放在其所屬的索引中。這樣,回答進來的順序並不重要;該數組在最後仍然以正確的順序排列。
  • 它跟蹤的我們多少反應仍然在等待進來,你可以知道,當你收到的一切,然後調用sendMessageToUser
  • 變量i聲明與letfor結構中的,所以這樣的話它有塊範圍,即你爲循環的每次迭代獲得一個單獨的變量。這樣,當你在回調中引用它時,它將與該版本的變量完全相同。
  • callback1callback2函數替換爲可處理這兩個變體的代碼(當response === null或不時)。

下面是代碼:

function queryDB(senderID, inMessage){ 
    var arr = inMessage.split(" "); 
    console.log(arr); 
    console.log('inside queryDB'); 
    // At first, use an array, so you can put back the asynchronous results in the correct order 
    var msgArray = []; 
    // Keep track of the number of asynchronous results you are still waiting for 
    var leftOver = arr.length; 
    // Use LET to make loop variable block scoped: that way you'll have the same value for 
    // it when the asynchronous callback is called 
    for(let i=0; i < arr.length; i++) { 
     var x = 'https://oreo-fd681.firebaseio.com/'+arr[i]+'.json'; 
     request({ 
      url: x, 
      method: 'GET' 
     }, function(error, response, body) { 
      console.log(response.body); 
      if (error) { 
       console.log('Error making api call ' + error); 
      } else if (response.body.error){ 
       console.log('Error making api call' + response.body.error); 
      } 
      else { 
       // Treat the two cases with the ternary operator 
       // and put the result at the correct index 
       msgArray[i] = response === null ? arr[i] : JSON.parse(response.body).key; 
       console.log(msgArray); 
       // Detect when you have collected all results 
       leftOver--; 
       if (!leftOver) { 
        // Join all the words together into one string and send it 
        sendMessageToUser(senderID, msgArray.join(' ')); 
       } 
      } 
     }); 
    } 
} 

就像我說的,我堅持了回調格局,但是當你使用的承諾和Promise.all方法事情變得更好。你應該看看。

+0

這就像一個魅力!感謝@trincot :)你錯過了在你的代碼中聲明'n'的意思。將調查Promise.all –

+0

是的,我現在用它應該是的表達式替換'n'。 – trincot

1

這不應該是一個問題。試着用

msg = msg.concat(arr[i]); 

使用CONCAT更換

msg+= (arr[i]); 

在所有四個msg +=分配

如果您arr值是它可以代替添加數字數值。

相關問題