2017-09-03 33 views
1

二方法調用什麼,我試圖完成的簡要概述:製作在同一請求

在前端,用戶能夠編輯他們的帳戶與使用形式的信息。然後,無論有多少個字段被編輯/觸摸,該表單都會發送到相同的HTTP請求。

我的想法是,請求會處理要編輯的字段。除了我不確定如何返回確認數據外,這種邏輯對我來說聽起來很合理。例如,它將如何知道所有請求何時完成/要顯示哪些確認和錯誤消息。

//Change information route 
router.post('/changeinformation', passport.authenticate('jwt', {session: false}), (req, res, next) => { 
    const changeInfo = { 
     changeEmail: req.body.changeEmail, 
     changeUsername: req.body.changeUsername 
    }; 

    if(changeInfo.changeUsername === true) { 
     const userInfo = { 
      email: req.body.email, 
      currentEmail: req.body.currentEmail 
     }; 
     Artist.getArtistByEmail(userInfo.email, (err, user) => { 
      if (err) throw err; 
      if (user) { 
       return res.json({success: false, msg: 'Email already exists'}); 
      } 
      else { 
       Artist.changeEmail(userInfo, (err, callback) => { 
        if (callback) { 
         console.log(callback); 
         return res.json({success: true, msg: 'Email has been changed successfully'}); 
        } 
       }); 
      } 
     }); 
    } 

    if(changeInfo.changeUsername === true) { 
     //Checks if username exists 
     const nameInfo = { 
      name: req.body.name, 
      currentName: req.body.currentName 
     }; 
     Artist.getArtistByName(userInfo.name, (err, user) => 
     { 
      if (err) throw err; 
      if (user) { 
       return res.json({success: false, msg: 'Name already exists'}); 
      } 
      else 
      { 
       Artist.changeName(userInfo, (err, callback) => { 
        if(callback) 
        { 
         console.log(callback); 
         return res.json({success: true, msg: 'Name has been changed successfully'}); 
        } 
       }); 
      } 
     }); 
    } 
}); 

我很抱歉,如果這對一些人來說似乎很明顯。我仍然在學習,我不確定如何處理這個問題。謝謝

回答

2

在這裏進行多次呼叫實際上並不需要,或者任何接近效率的地方。您可以根據選定的選項構建查詢和更新,而不是進行多個呼叫。

構建不同的方法來修改每個屬性也是完全沒有必要的。如果表達正確,標準貓鼬(實際上是真正的MongoDB)方法應該足夠描述預期的功能。這樣做,否則是繁瑣和不切實際的,和建築的查詢選項,而不是特定的屬性電話是你平時說到做到:

router.post('/changeinformation', 
    passport.authenticate('jwt', {session: false}), (req, res) => { 

    let query = { }, 
     update = { $set: { } }; 

    if (req.body.changeEmail) { 
    query['email'] = req.body.currentEmail; // presuming this is current 
    update.$set['email'] = req.body.email; 
    } 

    if (req.body.changeUsername) { 
    query['name'] = req.body.currentName; 
    update.$set['name'] = req.body.name; 
    } 

    // One call only 
    User.update(query,update,(err,result) => { 
    if (err) { 
     if (err.code === 11000) {  // Duplicate key error 
     res.json({ success: false, msg: 'email or name already exists' }); 
     } else { 
     res.json({ success: false, msg: err.message }); 
     } 
    } else { 
     if (result.n === 0) { 
     res.json({ success: false, msg: 'Requested details not found' }); 
     } else { 
     res.json({ success: true, msg: 'Details updated successfully' }); 
     } 
    } 

    }); 

}); 

所以不是妖異,使不同的電話,你只需檢查所提供的選項和構建從那裏查詢和更新語句。這些是「通過設計」只是普通的對象表示,就像任何對象一樣,您只需簡單地操縱結構來構建它們。

這裏的第一個主要出發點是使用查詢來檢查變化的「目標值是否存在」。這真的很低效。你真正要求的是這些值是「獨一無二的」,以便集合中的其他對象不能共享相同的nameemail。你強制執行此的方法是使用「指標」:

const userSchema = new Schema({ 
    ... 
    email: { type: String, required: true, unique: true }, 
    name: { type: String, required: true, unique: true } 
    ... 
}); 

架構中的貓鼬告訴那些"unique"屬性,以該財產是「獨一無二」的創建索引。如果您嘗試在集合中添加多個相同的值(即將用戶名更改爲與現有條目相同的值),那麼這會引發「重複鍵錯誤」,我們可以通過錯誤代碼捕獲該錯誤作出相應迴應

所以這是這段代碼的功能,通過測試返回錯誤代碼,當它被認定爲重複鍵錯誤給予響應相應的消息:

 if (err.code === 11000) { 
     res.json({ success: false, msg: 'email or name already exists' }); 
     } else { 
     res.json({ success: false, msg: err.message }); 
     } 

這是很多不是進行更直接單獨的查詢來測試目標值是否已經存在。而且它更加可靠,因爲在你的「查詢」和當前代碼中的後續「更新」之間,其他的東西實際上可以改變數據。因此,如果沒有強制執行唯一索引並檢查錯誤,您將面臨創建重複項的風險。因此,使用正確的工具來完成正確的工作。

這裏的其他檢查當然是看是否有任何內容與更新相匹配。這總是包含在.update()n屬性下的響應對象中,該屬性表示條件實際匹配的文檔數量。對於消息本身,您可以將它們保留爲「原樣」,並且我個人發現它是完全合理的,或者您可以在請求參數中使用類似的分支邏輯,與語句結構一樣,以確定特定的消息內容返回。

舉個例子:

let errStr = (req.body.changeEmail && req.body.changeUsername) 
    ? "email or name" 
    : (req.body.changeEmail) ? "email" : "name"; 
res.json({ success: false, msg: `${errStr} already exists` }); 

,希望你得到的總體思路。

但它比嘗試將不同呼叫鏈接在一起並在您不需要時提出多個請求要好得多。


作爲一個旁註,我們實際上有更多的現代和建議的方式來處理事情比使用回調嵌套。 Promise已經出現一段時間了,您也應該在支持async/await語法的環境中工作,因爲任何nodejs v8.xx發行版都會這樣做,並且實際上即將成爲長期支持(LTS)版本:

router.post('/changeinformation', 
    passport.authenticate('jwt', {session: false}), async (req, res) => { 

    let query = { }, 
     update = { $set: { } }; 

    if (req.body.changeEmail) { 
    query['email'] = req.body.currentEmail; // presuming this is current 
    update.$set['email'] = req.body.email; 
    } 

    if (req.body.changeUsername) { 
    query['name'] = req.body.currentName; 
    update.$set['name'] = req.body.name; 
    } 

    try { 
    let result = await User.update(query,update); 

    if (result.n === 0) { 
     let msgStr = (req.body.changeEmail && req.body.changeUsername) 
     ? "email or name" 
     : (req.body.changeEmail) ? "email" : "name"; 
     res.json({ success: false, msg: `Requested ${msgStr} not found` }); 
    } else { 
     res.json({ success: true, msg: 'Details updated successfully' }); 
    } 

    } catch(e) { 
    if (e.code === 11000) { 
     let errStr = (req.body.changeEmail && req.body.changeUsername) 
     ? "email or name" 
     : (req.body.changeEmail) ? "email" : "name"; 
     res.json({ success: false, msg: `${errStr} already exists` }); 
    } else { 
     res.json({ success: false, msg: e.message }); 
    } 
    } 
}); 

當你確實有一系列的異步函數需要解析時,它真的進入了它自己,以及在這種情況下我們真的試圖避免的東西。但是,即使包含try..catch塊的一般情況也至少具有更合理的流程,並且確實提高了代碼的可讀性。

+0

這正是我一直在尋找的。我知道我做這件事的方式有些根本錯誤。謝謝 –

1

第一個if(changeInfo.changeUsername === true)應按照您的邏輯if(changeInfo.changeEmail === true)

+0

你說得對。謝謝 –