2017-02-08 3 views
0

に応答を送信できませんmongooseを使ってMongoDB文書を更新し、更新が成功すると、私はjsonオブジェクトを明示的な応答で返します。私はmongooseからコールバックで応答を呼び出そうとすると、次のエラーが発生します。エクスプレス+マングース:</p> <p>次のコードでは、私が更新している:私は24時間以上この問題に不満を感じてきたと私はこれまで問題を絞り込むきたコールバック

更新はデータベースで成功し、コールバックからデータを取得します。すべてがうまくいっているという応答を送信する以外はすべて正常に動作します。

私はこの前に応答を送信しないでも、送信する前に何らかの方法でresオブジェクトに触れることはありません。コールバックが成功した場合に応答を送信する方法についてのヘルプを探しています。

エラー:

Updating user draftBooks 
/home/samuel/Documents/Github/Moirai/node_modules/mongoose/lib/utils.js:419 
     throw err; 
     ^

Error: Can't set headers after they are sent. 
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11) 
    at ServerResponse.header (/home/samuel/Documents/Github/Moirai/node_modules/express/lib/response.js:719:10) 
    at ServerResponse.send (/home/samuel/Documents/Github/Moirai/node_modules/express/lib/response.js:164:12) 
    at ServerResponse.json (/home/samuel/Documents/Github/Moirai/node_modules/express/lib/response.js:250:15) 
    at Promise.<anonymous> (/home/samuel/Documents/Github/Moirai/server/lib/stories.js:105:13) 
    at Promise.<anonymous> (/home/samuel/Documents/Github/Moirai/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8) 
    at emitOne (events.js:77:13) 
    at Promise.emit (events.js:169:7) 
    at Promise.emit (/home/samuel/Documents/Github/Moirai/node_modules/mongoose/node_modules/mpromise/lib/promise.js:79:38) 
    at Promise.fulfill (/home/samuel/Documents/Github/Moirai/node_modules/mongoose/node_modules/mpromise/lib/promise.js:92:20) 

マングーススキーマ:

var Schema = mongoose.Schema; 
// create user schema 
var userSchema = new Schema({ 
    user_id: String, 
    username: String, 
    password: String, 
    draftBooks: [{book_id: String}] 
}); 

// add draftBook 
userSchema.methods.addDraftBook = function (book_id, callback) { 
    return this.model('User').findOneAndUpdate(
    { _id: this.user_id }, // search query 
    { $push: { 'draftBooks': {'_id': book_id.toString()} } }, // update action 
    { upsert: true }, 
    callback 
); 
} 

エクスプレスルート:これは私にはかなり不満を残している

router.route('/') 
    .post((req, res, next) => { 
    // other stuff that works great 
    // req.storyData defined here 
    }) 
    .post((req, res) => { 
     // create update corresponding user 
     console.log("Updating user draftBooks"); 
     // res.json({}) works outside of callback 
     var userData = new user({ user_id: req.storyData.creator }); 
     userData.addDraftBook(req.storyData._id, (err, data) => { 
     if (err){ 
      res.json({message: err}); 
     } else { 
      res.json({message: "Should work"}); //gives error 
     } 
     }); 
    }); 

、私は、文法的に間違って何も表示されていないものを私は行方不明ですか?エラーメッセージがプリントアウトでのように、[OK]を

答えて

0

は、我々は見つける:あなたの急行路線でCan't set headers after they're sent.

は、あなたが二回res.json({});を書きました。あなたはmongooseメソッドから適切なデータを受け取っているようです。その後、res.json({message: 'gives error'});に電話してください。これは、あなたが明示的にそれを伝えているので、あなたが言うように、next()と呼ばれるときに発生します。そのようなエラーを処理するために、あなたが現在いることを書いたif-else文を書く:

blah blah (err, data) => { 
    if (err) { 
    res.json({ success: false, message: 'Gives error' }); 
    } else { 
    res.json({ success: true, data: data }); 
    } 
}); 

は最後 res.jsonコールを取り出します。あなたはコールバックですでにそれを送り返しているので、あなたはそれを必要としません。エクスプレスルートのコンテキストでは、resはレキシカルスコープのオブジェクトです(上記と思います)。上のスコープで定義されているので、ネストされた関数でアクセスできます。だからあなたのコールバックでそれを送るとき、あなたはPOST要求全体のためにそれを送ります。あなたはすでにあなたがエラーを取得だからこそ、RES内部でJSONを設定

res.json({message: "returns this response"}) 

実行

res.json({message: "Gives error"}). 

前:

+0

この構造は、私の元の設定が、doesnのを反映コールバックで発生したエラーの問題を解決しません。 'res.json'を条件文の中に入れても、エラーが発生します。コールバック以外の応答を追加して、応答はここでは機能しますが、コールバックでは機能しないことを示します。私は混乱する可能性があるので、これを更新します(エラーの原因と見なすことができますが、そうではありません)。 –

+0

ええと、私は仕事中ですし、あなたのスキーマメソッドは、通常の方法とは大きく異なりますので、答えを見つけ出すのに時間がかかりません。 なぜ、変数 'userData'を作成していますか? Mongoデータベースを照会してUserを取得し、フェッチされたユーザーに対してスキーマメソッドを直接呼び出すためにこれを再作成します。プロミスチェーンや非同期npmモジュールは、このためのきれいなコードを書くのに役立ちます。 最後に、「送信後にヘッダーを設定できません」というのは、複数の場所で 'res.json'を送信したことに由来します。それが起こった可能性は他にありません。 –

+0

私はそこに原因を特定できるかどうかを調べるために、スキーマを詳しく見ていきます。私は約束をすることを考えています。コードを分かち合うかどうかは分かります。私は応答が送信されているのではないかと疑っています。ルートの最後(デバッグ中にコメントアウト)で404応答があり、何かが送信されたかどうかを確認するために 'res.headersSent'をチェックします。これは誤っており、応答が得られなかった(要求側の投稿が失敗する)ため、実際に送信された応答がないと思うようになります。 –

0

あなたの問題は、このラインということです。 ヘッダーを2回設定することはできません。それ(res.jsonする値を与えるためにあまり意味がありません)を2回(1外側のコールバックの内側及び1)

このんではない理由:

 userData.addDraftBook(req.storyData._id, (err, data) => { 
    if (!err) 
     res.json({message: "successful data"}) 
    else 
     res.json({message: "returns this response"}) 
    }); 
+0

レスポンスがコールバック外で動作することを示すために、この行 'res.json({message:"はこのレスポンス "}を返す")を追加しました。エラーは引き続きコールバック内で発生します。問題をより明確にするために、これを削除します。この行を削除すると、私のテストを中断した 'Can not post/api/route'というエラーが表示されます。 –

+0

私はあなたのコードを試して、userData.addDraftBookを他の非同期関数(私は "要求"を使用しています)に置き換えました。 – masterG

関連する問題