Остановить дальнейшее выполнение кода - PullRequest
0 голосов
/ 31 мая 2018

У меня есть запрос:

  Character.count({'character.ownerid': msg.author.id}, function (err, count) {
    if (err) {
      throw err;
    }

    if (count > 3) {
      err.message = 'Too many characters';
      //create error explanation and throw it
      throw err;
    }
  })

Если произойдет какая-либо из ошибок, мне нужно выйти из родительской функции целиком.Я не могу поставить возврат в этом запросе, так как он выходит только из этого метода.Я думал, что есть возможность сделать обратный вызов, как:

Character.count({'character.ownerid': msg.author.id}, function (err, count, stop) {

Но как с этим работать?Это внутри анонимной функции, я не знаю, где разместить ее содержимое.Я также пытался использовать try / catch, но не могу выбросить ошибки во внешний обработчик из-за Error: Unhandled "error" event. ([object Object]), см. Код ниже:

Character.count({'character.ownerid': msg.author.id}, function (err, count) {
  if (err) {
    throw err;
  }

  if (count > 3) {
    var err = {};
    err.message = 'Too many characters';
    throw err;
  }
}).then((count) => {
  console.log('all good we may continue');
  console.log(count);
}).catch((err) => {
  if (err != undefined && err.length > 0) {
    msg.reply(err.message);
    return 0; //exit parent function?
  }
});

Но даже если это сработало, я неуверен, что этот код будет делать то, что мне нужно.Запрос асинхронный, так что, если остальная часть кода будет запущена до then?Это вообще возможно?

Так что мне нужно как-то return 0; родительской функции как-то, и если есть какие-то ошибки, мне нужен обработчик для них.Есть идеи для этого?

1 Ответ

0 голосов
/ 31 мая 2018

Вы, кажется, упускаете понятие.Во-первых, как уже говорилось, все операции mongoose возвращают Promise или, по крайней мере, объект типа «Promise like», который можно сразу разрешить с помощью then() вместо передачи функции обратного вызова.Это может быть представлено двумя способами.

Либо с синтаксисом async/await и блоком try..catch:

const { Schema } = mongoose = require('mongoose');

const uri = 'mongodb://localhost/test';

mongoose.set('debug', true);
mongoose.Promise = global.Promise;

const characterSchema = new Schema({
  name: String
});

const Character = mongoose.model('Character', characterSchema);

const log = data => console.log(JSON.stringify(data,undefined,2));

const doCount = async () => {
  let count = await Character.count();

  if (count > 3)
    throw new Error("too many charaters");

  return count;

};


(async function() {

  try {
    const conn = await mongoose.connect(uri);

    await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()))

    await Character.insertMany(
      ["Huey","Duey","Louie"].map(name => ({ name }))
    );

    let count = await doCount();
    log({ count });

    await Character.create({ name: 'Donald' });

    let newCount = await doCount();
    console.log("never get here");


  } catch(e) {
    console.error(e)
  } finally {
    mongoose.disconnect();
  }

})()

Или со стандартным синтаксисом then() и catch():

const { Schema } = mongoose = require('mongoose');

const uri = 'mongodb://localhost/test';

mongoose.set('debug', true);
mongoose.Promise = global.Promise;

const characterSchema = new Schema({
  name: String
});

const Character = mongoose.model('Character', characterSchema);

const log = data => console.log(JSON.stringify(data,undefined,2));

function doCount() {
  return Character.count()
    .then(count =>  {

      if (count > 3)
        throw new Error("too many charaters");

      return count;
    });

};


(function() {

  mongoose.connect(uri)
    .then(conn => Promise.all(
      Object.entries(conn.models).map(([k,m]) => m.remove())
    ))
    .then(() => Character.insertMany(
      ["Huey","Duey","Louie"].map(name => ({ name }))
    ))
    .then(() => doCount())
    .then(count => log({ count }))
    .then(() => Character.create({ name: 'Donald' }))
    .then(() => doCount())
    .then(() => console.log("never get here"))
    .catch(e => console.error(e))
    .then(() => mongoose.disconnect() );

})()

И вывод обоих списков одинаков:

Mongoose: characters.remove({}, {})
Mongoose: characters.insertMany([ { _id: 5b0f66ec5580010efc5d0602, name: 'Huey', __v: 0 }, { _id: 5b0f66ec5580010efc5d0603, name: 'Duey', __v: 0 }, { _id: 5b0f66ec5580010efc5d0604, name: 'Louie', __v: 0 } ], {})
Mongoose: characters.count({}, {})
{
  "count": 3
}
Mongoose: characters.insertOne({ _id: ObjectId("5b0f66ec5580010efc5d0605"), name: 'Donald', __v: 0 })
Mongoose: characters.count({}, {})
Error: too many charaters
    at doCount (/home/projects/characters/index.js:20:11)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

Как вы можете видеть, функция с радостью возвращает свое значение, где count остается 3 или ниже, но затем выдаетисключение, которое останавливает дальнейшее выполнение, когда count будет больше 3, поскольку сообщение "never get here" никогда не регистрируется.

Таким образом, здесь нет необходимости в «обратных вызовах», и вы не будете использовать его, если только выОбернутый в Обещание может все равно выполнить тот же тип обработки ошибок.

Но если у вас есть "ошибка", то throw ошибка.Это прекрасно работает в цепочке обещаний, но «обратный вызов», который не возвращается как обещание, просто не является частью этой цепочки и никогда не может быть «пойман».Так что просто не используйте обратный вызов, когда вам это не нужно.

Только для ударов, завершение обратного вызова с обещанием будет сделано как:

function doCount() {
  return new Promise((resolve,reject) =>
    Character.count().exec((err,count) => {

      if (count > 3)
        reject(new Error("too many charaters"));

      resolve(count);
    })
  );
};

Но это не отмеченонеобходимо, учитывая, что нативные методы возвращают что-то, что вы в любом случае можете разрешить как Обещание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...