Как объединить строку, которая создается в течение двух вызовов обратного вызова через Mon goose в Node.js? - PullRequest
1 голос
/ 27 февраля 2020

У меня есть две модели, которые связаны друг с другом. Если документ mon go для первой модели успешно удален, я должен удалить его родительский документ.

Исключение может возникнуть при попытке выполнить второе удаление или нет. С ошибками или без них я хотел бы объединить первое и второе сообщения, но область действия переменной «message» внутри «findOneAndDelete» отличается от ее родителя.

Как выполнить sh это требование ?

Приведенный ниже фрагмент кода работает нормально, за исключением того, что доставляется только основное сообщение.

    var id = req.params.id;
    var valid = mongoose.Types.ObjectId.isValid(id);

    if (valid) {

        MyModel
        .findByIdAndDelete({"_id": id})
        .exec(function (err, result) {
            var message = "Item has been removed successful.";
            if (!result) {
                message = "Error at deleting an about item.";
            } else {

                // finding and deleting related about image item
                var query = { "id": id };

                SecondModel
                    .findOneAndDelete(query).exec(function (err, result) {

                    // deletion is OK, but the concatenation does not work
                    // how to return this "message" scope to its parent?

                    message += " Image item has been removed successful.";
                    if (!result) {
                        message += " Error trying to remove about image item.";
                    }

                });

            }

            // the concatenation should be returned here

            responseUtilities.sendJsonResponse(res, err, {"message": message});
        });
    } else {
        responseUtilities.sendJsonResponse(res, false, { "message": "Item id is not valid." });
    }



Ответы [ 3 ]

1 голос
/ 27 февраля 2020

Рад, что вы нашли ответ. Вот несколько идей по структуре и стилю, которые облегчат чтение этого кода (вами или вашим коллегой в будущем) и облегчат его отладку и расширение. Начните с создания небольших функций с обещанием возврата для двух асинхронных операций c.

function deleteAboutWithId(id) {
  return new Promise((resolve, reject) => {
    AboutModel.findByIdAndDelete({"_id": id}).exec(function (err, result) {
      err ? reject(err) : resolve(result)
    })
  })
}

function deleteImageWithAboutId(id) {
  return new Promise((resolve, reject) => {
    AboutImageModel.findOneAndDelete({ aboutId: id }).exec(function (err, result) {
      err ? reject(err) : resolve(result)
    })
  })
}

Хорошим преимуществом является то, что они могут быть проверены модулем, повторно использованы, обобщены и т. Д. c. Другое преимущество заключается в том, что их использование делает вашу бизнес-логику c понятной и лаконичной. Код читается так, как вы бы описали функцию коллеге ...

  • Удалить элемент
  • Удалить изображение
  • Если оба успешно, ответьте на составное сообщение об успехе
  • Если одно из них не удалось, ответьте (возможно) на составное сообщение об ошибке

Функция publi c:

const msgIdError = 'About item id is not valid.'
const msgItemSuccess = 'About item has been removed successful.'
const msgImageSuccess = ' Its image item has also been removed successful.'
const msgItemError = 'Error at deleting an about item.'
const msgImageError = ' Error trying to remove about image item.'

module.exports.delete = function (req, res) {
  const idAbout = req.params.idAbout
  if (!mongoose.Types.ObjectId.isValid(idAbout)) {
    responseUtilities.sendJsonResponse(res, false, { "message": msgIdError })
  }
  let message = ''
  deleteAboutWithId(idAbout).then(() => {
    message += msgItemSuccess
    return deleteImageWithAboutId(idAbout)
  }).then(() => {
    message += msgImageSuccess
    responseUtilities.sendJsonResponse(res, err, { "message": message })
  }).catch(err => {
    // if message is empty, the first block threw the error
    message += message.length ? msgImageError : msgItemError
    responseUtilities.sendJsonResponse(res, err, { "message": message });
  })
}

Несколько быстрых заметок : (1) приятно убрать струны с дороги. Они могут когда-нибудь быть сохранены в конфигурации, переведены на другие языки и т. Д. c. (2) Он немного очищает код, чтобы проверить наличие недопустимых входов в верхней части и вывести из строя в верхней части , если входные данные недействительны.

0 голосов
/ 27 февраля 2020

Query.exec получает обратный вызов, который обрабатывается позже.

При внешнем вызове Query.exec, когда нет результатов, вы отправляете ответ. В противном случае вы выполняете другой Query.exec, который обрабатывает другой обратный вызов, который не возвращает ответа.

Быстрым решением было бы отправить ответ во внутренний Query.exec.

Эта последовательность операций выполняется в цепочечном порядке и может быть лучше скоординирована с помощью обещаний. Например,

const message = (prefix='') => msg => `${prefix} ${msg}`
const asyncChain = (outer, inner) => { 
  return outer
  .then(message())
  .then(outerResult => inner
      .then(message(outerResult))
      .catch(message(outerResult))
  )
  .catch(message())
  .then(console.log);
}

asyncChain(Promise.resolve('outer1✅'), Promise.resolve('inner1✅'))
// outer1✅ inner1✅

asyncChain(Promise.resolve('outer2✅'), Promise.reject('inner2❌'))
// outer2✅ inner2❌

asyncChain(Promise.reject('outer3❌'), Promise.resolve('inner3✅'))
// outer3❌

Учитывая, что Query.exec возвращает объект Promise, можно координировать операции запроса следующим образом:

MyModel.findByIdAndDelete({ _id: id })
  .exec()
  .then(function() {
    return "Item has been removed successful.";
  })
  .then(function(deleteItemSuccessResult) {
    return SecondModel.findOneAndDelete(query)
      .exec()
      .then(function() {
        return (
          deleteItemSuccessResult + " Image item has been removed successful."
        );
      })
      .catch(function() {
        return (
          deleteItemSuccessResult + " Error trying to remove about image item."
        );
      });
  })
  .catch(function() {
    return "Error trying to remove item";
  })
  .then(function(message) {
    responseUtilities.sendJsonResponse(res, err, { message: message });
  });
0 голосов
/ 27 февраля 2020

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

module.exports.delete = function (req, res) {

    var idAbout = req.params.idAbout;
    var valid = mongoose.Types.ObjectId.isValid(idAbout);

    if (valid) {

        var message;

        AboutModel
        .findByIdAndDelete({"_id": idAbout})
        .exec(function (err, result) {

            message = "About item has been removed successful.";

            if (!result) {
                message = "Error at deleting an about item.";
            } else {

                new Promise((resolve, reject) => {
                    deleteImage(idAbout);
                    resolve();
                }).then(() => {
                    message += " Its image item has also been removed successful.";
                    responseUtilities.sendJsonResponse(res, err, { "message": message });
                }).catch(
                    error => {
                        message += " Error trying to remove about image item. ";
                        message += error.message;
                        responseUtilities.sendJsonResponse(res, err, { "message": message });
                    }
                );
            }

        });
    } else {
        responseUtilities.sendJsonResponse(res, false, { "message": "About item id is not valid." });
    }
};

// outside function

function deleteImage(idAbout) {
    var query = { "aboutId": idAbout };
    AboutImageModel.findOneAndDelete(query).exec(function (err, result) {});
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...