mongodb dup 密钥错误 11000 使节点服务器崩溃

mongodb dup key error 11000 crashes node server

重复键 E11000 是预期的行为,但服务器崩溃不是。重复键错误来自我在电子邮件中的唯一索引。

控制器方法:

   exports.saveOAuthUserProfile = function(req, profile, done) {

  User.findOne({
    provider: profile.provider,
    providerId: profile.providerId
  }, function(err, user) {
    if (err) {
      return done(err);
    } else {
      if (!user) {
        var possibleUsername = profile.username || ((profile.email) ? profile.email.split('@')[0] : '');

        User.findUniqueUsername(possibleUsername, null, function(availableUsername) {
          profile.username = availableUsername;

          user = new User(profile);

          user.save(function(err) {
            if (err) {
              var message = getErrorMessage(err);
console.log(message);
              //req.flash('error', message);
              return res.redirect('/signup');
            }

            return done(err, user);
          });
        });
      } else {
        return done(err, user);
      }
    }
  });
};

getErrorMessage 方法:

var getErrorMessage = function(err) {

    var message = '';

    // If an internal MongoDB error occurs get the error message
    if (err.code) {
        switch (err.code) {
            // If a unique index error occurs set the message error
            case 11000:
                message = 'Duplicate Key';
                break;
            case 11001:
                message = 'Username already exists';
                break;
            // If a general error occurs set the message error
            default:
                message = 'Something went wrong';
        }
    } else {
        // Grab the first error message from a list of possible errors
        for (var errName in err.errors) {
            if (err.errors[errName].message) message = err.errors[errName].message;
        }
    }

    return message;
};

UserSchema 中的电子邮件:

email: {
        type: String,
        unique: 'That email is already taken',
        match: [/.+\@.+\..+/, 'Please use a valid e-mail address']
},

cli 输出:

λ node server
Server running at http://localhost:3000/
GET / 200 26.879 ms - 1347
GET /lib/angular-route/angular-route.min.js 200 12.790 ms - 4408
GET /lib/angular-resource/angular-resource.min.js 200 13.863 ms - 3598
GET /modules/example/example.client.module.js 200 14.557 ms - 30
GET /modules/example/controllers/example.client.controller.js 200 12.595 ms - 240
GET /modules/example/config/example.client.routes.js 200 12.024 ms - 547
GET /lib/angular/angular.min.js 200 77.183 ms - 145234
GET /modules/users/users.client.module.js 200 24.306 ms - 28
GET /modules/users/services/authentication.client.service.js 200 25.467 ms - 168
GET /application.js 200 23.834 ms - 536
GET /modules/articles/articles.client.module.js 200 27.471 ms - 31
GET /modules/articles/services/articles.client.service.js 200 28.066 ms - 234
GET /modules/example/views/example.client.view.html 200 1.968 ms - 83
GET /lib/angular/angular.min.js.map 304 10.579 ms - -
GET /lib/angular-route/angular-route.min.js.map 304 17.932 ms - -
GET /lib/angular-resource/angular-resource.min.js.map 304 31.510 ms - -
GET /signin 200 5.881 ms - 606
GET /oauth/google 302 2.573 ms - 0
Duplicate Key
C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:108
  if (this.ended && !this.hasRejectListeners()) throw reason;
                                                      ^
ReferenceError: res is not defined
    at EventEmitter.<anonymous> (C:\Users\lotus\Desktop\mastering_mean\application\app\controllers\users.server.controller.js:107:22)
    at EventEmitter.<anonymous> (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:174:48)
    at EventEmitter.emit (events.js:107:17)
    at Promise.safeEmit (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:81:21)
    at Promise.reject (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:109:15)
    at Promise.error (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\promise.js:94:15)
    at Promise.resolve (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\promise.js:112:24)
    at C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\document.js:1578:39
    at handleError (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:40:22)
    at next_ (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:75:26)
    at EventEmitter.fnWrapper (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\hooks-fixed\hooks.js:171:15)
    at EventEmitter.<anonymous> (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:174:48)
    at EventEmitter.emit (events.js:107:17)
    at Promise.safeEmit (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:81:21)
    at Promise.reject (C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\node_modules\mpromise\lib\promise.js:109:15)
    at C:\Users\lotus\Desktop\mastering_mean\application\node_modules\mongoose\lib\model.js:263:20

正如您在 cli 输出中看到的那样,我的 getErrorMessage 函数正在正确检索错误,我可以 console.log(message) 但此时节点服务器崩溃导致错误消息 res 未定义。

节点版本:0.12.4 MongoDB shell 版本:3.0.3 快递 4.12.4 猫鼬 4.0.5 Win 7 专业版 x64

我可以提供更多信息吗?

更新: 添加调用控制器方法的通行证策略

   module.exports = function() {
  passport.use(new GoogleStrategy({
    clientID: config.google.clientID,
    clientSecret: config.google.clientSecret,
    callbackURL: config.google.callbackURL,
    passReqToCallback: true
  },
  function(req, accessToken, refreshToken, profile, done) {
    var providerData = profile._json;
    providerData.accessToken = accessToken;
    providerData.refreshToken = refreshToken;

    var providerUserProfile = {
      firstName: profile.name.givenName,
      lastName: profile.name.familyName,
      fullName: profile.displayName,
      email: profile.emails[0].value,
      username: profile.emails[0].value.replace(/@.*$/,""),
      provider: 'google',
      providerId: profile.id,
      providerData: providerData
    };

    users.saveOAuthUserProfile(req, providerUserProfile, done);
  }));

护照策略处理程序可以选择通过 req(通过设置 passReqToCallback),但不能通过 res。因此,如果您需要策略处理程序中的响应对象,或从中调用的任何函数(如您的 users.saveOAuthUserProfile),您需要使用 Express 将响应对象添加到请求对象的事实,您可以通过req.res.

所以这个:

return res.redirect('/signup');

需要这样:

return req.res.redirect('/signup');