鍍金池/ 問答/數(shù)據(jù)庫  網(wǎng)絡(luò)安全  HTML/ 數(shù)據(jù)庫操作套在回調(diào)函數(shù)中就出錯(cuò)

數(shù)據(jù)庫操作套在回調(diào)函數(shù)中就出錯(cuò)

實(shí)現(xiàn)一個(gè)注冊(cè)功能

user.post('/register', async(ctx) => {
    let {username, password, rePassword} = ctx.request.body;
    
    if (!username) {
        responseClient(ctx, 400, 2, '用戶名不可為空');
        return;
    }
    if (!password) {
        responseClient(ctx, 400, 2, '密碼不可為空');
        return;
    }
    if (password !== rePassword) {
        responseClient(ctx, 400, 2, '兩次密碼不一致');
        return;
    }   

    try{
       await User.findOne({username}, function(err, doc){
            if(err){
                 responseClient(ctx);
             }

             if(doc){
                 responseClient(ctx, 200, 1, '用戶名已存在');
                 return;  
             }else{
                 //保存到數(shù)據(jù)庫
                let user = new User({
                     username: username,
                     password: password,
                     type: 'user'
                 });

                 user.save(function(err, doc){
                     if(err){
                         console.log(err);
                     }
                     if(doc){
                         let data = {};
                         data.username = doc.username;
                         data.userType = doc.type;
                         data.userId = doc._id;
                         responseClient(ctx, 200, 0, '注冊(cè)成功', data);
                         return;
                     }
                 });   
             }
         })

           }

    }catch(e){
        responseClient(ctx);
    }
})

當(dāng)我這樣寫的時(shí)候有時(shí)候會(huì)注冊(cè)成功有時(shí)候就會(huì)提示AssertionError [ERR_ASSERTION]: headers have already been sent

后來試了下這種寫法就沒問題

user.post('/register', async(ctx) => {
    let {username, password, rePassword} = ctx.request.body;
    
    if (!username) {
        responseClient(ctx, 400, 2, '用戶名不可為空');
        return;
    }
    if (!password) {
        responseClient(ctx, 400, 2, '密碼不可為空');
        return;
    }
    if (password !== rePassword) {
        responseClient(ctx, 400, 2, '兩次密碼不一致');
        return;
    }   

    try{
        let doc = await User.findOne({username})
        if(doc){
            responseClient(ctx, 200, 1, '用戶名已存在');
            return
        }else{
            let user = new User({
                    username: username,
                    password: password,
                    type: 'user'
                });

            let newUser = await user.save();
            let data = {};
            data.username = newUser.username;
            data.userType = newUser.type;
            data.userId = newUser._id;
            responseClient(ctx, 200, 0, '注冊(cè)成功', data);
            return;
        }

    }catch(e){
        responseClient(ctx);
    }
})

responseClient

    responseClient(ctx,httpCode = 500, code = 3,message='服務(wù)端異常',data={}) {
        let responseData = {};
        responseData.code = code;
        responseData.message = message;
        responseData.data = data;
        ctx.status = httpCode;
        ctx.body = responseData;
    }

請(qǐng)問第一種是我哪里寫錯(cuò)了嗎?正常的寫法應(yīng)該怎么寫?

圖片描述

回答
編輯回答
苦妄

User.findOne()的內(nèi)容能發(fā)一下嗎?User.findOne()是不是返回Promise?你這樣寫試試:

user.post('/register', async(ctx) => {
let {username, password, rePassword} = ctx.request.body;

if (!username) {
    responseClient(ctx, 400, 2, '用戶名不可為空');
    return;
}
if (!password) {
    responseClient(ctx, 400, 2, '密碼不可為空');
    return;
}
if (password !== rePassword) {
    responseClient(ctx, 400, 2, '兩次密碼不一致');
    return;
}   

try{
   User.findOne({username}).then(function(doc,err){
        if(err){
             responseClient(ctx);
         }

         if(doc){
             responseClient(ctx, 200, 1, '用戶名已存在');
             return;  
         }else{
             //保存到數(shù)據(jù)庫
            let user = new User({
                 username: username,
                 password: password,
                 type: 'user'
             });

             user.save(function(err, doc){
                 if(err){
                     console.log(err);
                 }
                 if(doc){
                     let data = {};
                     data.username = doc.username;
                     data.userType = doc.type;
                     data.userId = doc._id;
                     responseClient(ctx, 200, 0, '注冊(cè)成功', data);
                     return;
                 }
             });   
         }
     })

       }

}catch(e){
    responseClient(ctx);
}

})

2018年3月11日 13:26
編輯回答
逗婦乳

先說錯(cuò)在什么地方

if(err){
    responseClient(ctx);
    // 此處應(yīng)該有return
}

err不為空時(shí)已經(jīng)調(diào)用了responseClient,但是又繼續(xù)往下走,這時(shí)doc顯然是空,所以會(huì)走到else里面
,無論成功或是異常(我也不知道,因?yàn)榭床坏綀?zhí)行結(jié)果),最后都會(huì)再執(zhí)行一次responseClient。2次調(diào)用向客戶端響應(yīng)的方法,就會(huì)出現(xiàn):

headers have already been sent

第一種方式有點(diǎn)不知所云。callback和await/async本來是二選一,為什么第一種寫法既有await又有callback?
至于正確的寫法,只能說造成問題的主要是你沒有return,后面的邏輯是否正確還要你自己執(zhí)行看看。

2018年3月10日 09:00