>

이것이 1000 번 응답 된 것을 알고 있지만 내 인생에서 왜 헤더를 두 번 이상 보내려고하는지 알 수 없습니다. 따라서 중복으로 표시하려는 경우 중복 이유와 내가 잘못한 부분을 설명하십시오. 약간의 설명 없이는 링크가 거의 도움이되지 않습니다.

알겠습니다. 확인 링크를 두 번 클릭하여 사용자에게 복제를 시도하기 위해 확인 토큰을 두 번 다시 보내려고 할 때 미들웨어/컨트롤러를 실행하는 간단한 확인 경로가 있습니다.

사용자의 토큰은 여전히 ​​내 DB에 있지만 (이를 변경할 계획이지만) 오류를 일으키는 줄은 사용자 프로필을 확인하여 확인되었는지 확인하기 때문에 중요하지 않습니다.

router.post('/confirmation', 
  user.confirmationPost);

exports.confirmationPost = function (req, res, next) {
    // Find a matching token
    Token.findOne({ token: req.body.token }, function (err, token) {
        if (!token) return res.status(400).send({ type: 'not-verified', message: 'We were unable to find a valid token. Your token my have expired.' });
        // If we found a token, find a matching user
        User.findOne({ _id: token._userId }, function (err, user) {
            if (!user) return res.status(400).send({ message: 'We were unable to find a user for this token.' });
            if (user.isVerified) return res.status(400).send({ message: 'This user has already been verified.' }); // THIS LINE CAUSES THE ERROR
            // Verify and save the user
            user.isVerified = true;
            user.save(function (err) {
                if (err) { return res.status(500).send({ message: err.message }); }
                res.redirect(`${config.siteURL}/dash`);
            });
        });
    });
    next();
};

오류 메시지

Error: Can't set headers after they are sent.


  • 답변 # 1

    내 문제를 알아 냈는데 문제는 next() 였습니다.  결국, 헤더를 다시 전달/설정하려고 시도한 res.send/json 이후에 호출되었습니다.

  • 답변 # 2

    새로운 대기/비동기 사용을 제안하십시오. 콜백 스타일은 오류가 발생하기 쉽습니다. 비동기 제어를 정렬하는 데 어려움이 있습니다.

    Express 프레임 워크는 콜백 스타일이므로 https://github.com/tj/co를 사용할 수 있습니다 처리기 사용 대기/비동기, 그러나 마지막으로 http://koajs.com/이 더 좋습니다.

  • 답변 # 3

    문제를 파악한 후 응답을 정답으로 표시하십시오!

    앞으로 ES7의 async/await 구문을 사용하여 코드 스 니펫을 작성했습니다. 코드가 더 길어 보일 수 있지만 이해하기 쉬워야합니다. 또한 모든 반환 기능을 확장하고 주석을 추가하여 길이에 기여했습니다.

    /*
     * Notice how the keyword `async` is in front of the arrow function. 
     * This tags the function as asynchronous and returns a promise. 
     * It also allows us to use the `await` keyword which waits for the function 
     * to return whatever follows the await keyword. Only after it returns will 
     * the function continue.
     */ 
    exports.confirmationPost = async (req, res, next) => {
        // The await keyword here makes sure that Token.findOne() returns (resolves/rejects promise) before continuing the function.
        // However, this DOES NOT mean that the program hangs, as it would for a synchronous function. 
        // Other functions can run while this instance of the function waits for Token.findOne() to return.
        let token = await Token.findOne({ token: req.body.token });
        // Once Token.findOne returns, you have access to a then callback.
        token.then((err, token) => {
            if (!token) { 
                // While this is completely fine, I suggest you use next() and pass in an error obj to it and let your middleware handle the return of the error to the client.
                return res.status(400).send({ 
                    type: 'not-verified', 
                    message: 'We were unable to find a valid token. Your token my have expired.' 
                });
            }
            // Once again, we use await to wait for User.findOne() to return.
            let user = await User.findOne({ _id: token._userId });
            // Once User.findOne returns, you have access to a then callback.
            user.then((err, user) => {
                if (!user) {
                    return res.status(400).send({ 
                        message: 'We were unable to find a user for this token.' 
                    });
                }
                if (user.isVerified) {
                    return res.status(400).send({ 
                        message: 'This user has already been verified.' 
                    }); 
                }
                // Verify and save the user
                user.isVerified = true;
                // You can simply chain the then callback instead of making a new variable.
                user.save().then(err => {
                    if (err) { 
                        return res.status(500).send({ 
                            message: err.message 
                        }); 
                    }
                    res.redirect(`${config.siteURL}/dash`);
                });
            });
        });
    }
    
    

    약속을 사용하고 노드 및 몽고와 비동기/대기 할 때 머리에 못을 박는 아래 두 링크를 확인하십시오.

    <올>

    https://medium.com/@rossbulat/using-promises-async-await-with-mongodb-613ed8243900

    http://www.codingpedia.org/ama/cleaner-code-in-nodejs-with-async-await-mongoose-calls-example

관련 자료

  • 이전 ios - Xcode 821이 포함 된 Here Maps Premium SDK를 포함한 아카이브를 제출할 수 없습니다
  • 다음 android - ImageView에서 이미지를 확대하지만 자르는 것을 방지하는 방법은 무엇입니까?