Ошибка: обратный вызов уже был вызван в обратной связи - PullRequest
0 голосов
/ 28 мая 2018

У меня есть следующий код:

"use strict";
const Raven = require("raven");
Raven.config(
    "test"
).install();

module.exports = function(Reservation) {
  function dateValidator(err) {
    if (this.startDate >= this.endDate) {
      err();
    }
  }

  function sendEmail(campground) {
    return new Promise((resolve, reject) => {
      Reservation.app.models.Email.send(formEmailObject(campground), 
        function(
          err,
          mail
        ) {
           if (err) {
            console.log(err);
            Raven.captureException(err);
            reject(err);
           } else {
             console.log(mail);
             console.log("email sent!");
             resolve(mail);
           }
       });
   });
} 

  function formEmailObject(campground) {
    return {
      to: "loopbackintern@yopmail.com",
      from: "noreply@optis.be",
      subject: "Thank you for your reservation at " + campground.name,
      html:
        "<p>We confirm your reservation for <strong>" +
        campground.name +
        "</strong></p>"
    };
   }

Reservation.validate("startDate", dateValidator, {
 message: "endDate should be after startDate"
});

Reservation.observe("after save", async function(ctx, next) {
 try {
  const campground = await Reservation.app.models.Campground.findById(
    ctx.instance.campgroundId
  );
  const mail = await sendEmail(campground);
  next();
 } catch (e) {
  Raven.captureException(e);
  next(e);
 }
});
};

Извините за плохое форматирование.Когда поток завершен, я получаю эту ошибку:

(node:3907) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Callback was already called.

Я вызываю обратный вызов next () в двух местах, один в коде попытки и один в коде перехвата.Я предполагаю, что когда все идет хорошо, следующий обратный вызов вызывается только один раз, и то же самое, когда он идет не так.Но кажется, что он вызывается дважды, и я не знаю почему.

Я также пытался вызвать next вне кода try / catch, но это приводит к той же ошибке.Если я оставлю только следующее, которое вызывается внутри кода catch, это не выдает ошибку.

Есть идеи?Спасибо!

Ответы [ 3 ]

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

если вы используете асинхронную функцию, которую вы не должны явно вызывать следующим, она автоматически вызывается .

проверьте эту проблему github для обратной петлиasync / await

, поэтому ваш хук может выглядеть следующим образом:

 Reservation.observe("after save", async ctx => {
  try {
    const campground = await Reservation.app.models.Campground.findById(
      ctx.instance.campgroundId
    );
    const mail = await sendEmail(campground);
  } catch (e) {
    Raven.captureException(e);
    throw e;
  }
});

NB: вам не нужно оборачивать его в try catch, если вы не хотитеизменить / работать с ошибкой.

0 голосов
/ 14 июня 2018

После прочтения этой статьи я создал файл await-handler.js, который включает следующий код.

module.exports = (promise) =>
  promise
    .then(data => ({
        ok: true,
        data
    }))
    .catch(error =>
      Promise.resolve({
        ok: false,
        error
      })
    );

Затем в файле MyModel.js я создал асинхронную функцию дляполучить значение из базы данных следующим образом.

const awaitHandler = require("./../await-handler.js")
const getMaxNumber = async (MyModel) => {
    let result = await awaitHandler(MyModel.find());
    if (result.ok) {
        if (result.data.length) {
            return result.data.reduce((max, b) => Math.max(max, b.propertyName), result.data[0] && result.data[0].propertyName);
        } else {
            return 0;
        }
    } else {
        return result.error;
    }
}

Согласно ответу @ Mehari, я прокомментировал вызов метода next() следующим образом: -

module.exports = function(MyModel) {
   MyModel.observe('before save', async(ctx, next) => {
       const maxNumber = await getMaxNumber (MyModel);
       if(ctx.instance) {
            ...
            set the required property using ctx.instance.* 
            like createdAt, createdBy properties
            ...
            // return next();
       } else {
            ...
            code for patch
            ...
            // return next();
       }
   })
}

Это устраняет предупреждениепроблема при каждом запуске сохранения конечной точки.

Но проблема предупреждения все еще появляется, когда я запускаю конечную точку для загрузки ресурса. Как http://localhost:3000/api/MyModel Раньше проблема возникала только тогда, когда срабатывает ловушка операции before save.

После возникновения этой проблемы я проверил добавление хуков операций access и loaded и обнаружил, что предупреждения выдаются после хука операций loaded.

MyModel.observe('access', (ctx, next) => {
    return next();
})

MyModel.observe('loaded', (ctx, next) => {
    return next();
})

Что может иметьвызвал эту проблему и как она может быть решена?

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

Вы должны объявить ваш метод sendEmail как асинхронный, так как он возвращает обещание.

асинхронная функция sendEmail (campground) {...}

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