Исправление порядка оценки на JavaScript с использованием нескольких .then - PullRequest
0 голосов
/ 28 мая 2018

Я страдаю, чтобы сделать этот код синхронным в JavaScript.

В комментариях (1, 2 и 3) говорится о том, что происходит по порядку, сейчас он сохраняет владельца, прежде чем, возможно, создаст новый бар.

Мне нужно найти один, возможно saveBar, затем saveOwner.

function setMyBar(req, res, next) {
  const owner = req.queryOwner;
  Bar.findOne({
    placeId: req.body.placeId
  })
    .then((bar) => {
      if(bar){
        owner.bar = bar; //1
        return owner;
      }else{
        barCtrl.saveBar(req.body.name, req.body.placeId, req.body.longitude, req.body.latitude)
        .then((savedBar) => {
          owner.bar = savedBar; //3
          return owner;
        })
        .catch(e => {return Promise.reject(err) })
      }
    }).then(() => {
      owner.save()
        .then(savedOwner => res.json(savedOwner)) //2
        .catch(e => next(e));
    })
    .catch(e => next(e));
}

Ответы [ 4 ]

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

Вы также можете попытаться использовать асинхронные функции ES7 или синтаксис async / await, что позволит вам писать свой код МНОГО более синхронно, но при этом он будет выполняться асинхронно и параллельно, если вы того пожелаете.Он поддерживается во всех текущих версиях основных браузеров (кроме IE), а также в движке Google V8, который используется Node.js.

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

async function setMyBar(req, res, next) {
    const owner = req.queryOwner;
    try {
        let bar = await Bar.findOne({
            placeId: req.body.placeId
        });

        if (bar) {
            owner.bar = bar;
        } else {
            let savedBar = await barCtrl.saveBar(req.body.name, req.body.placeId, req.body.longitude, req.body.latitude);
            owner.bar = savedBar;
        }

        res.json(await owner.save());
    } catch (e) {
        next(e);
    }
}

Также обратите внимание, что ключевое слово async в объявлении функции async гарантирует, что ваша функция всегда возвращает обещание!

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

https://developers.google.com/web/fundamentals/primers/async-functions

https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8

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

попробуйте

function setMyBar(req, res, next) {
  const owner = req.queryOwner;
  Bar.findOne({
    placeId: req.body.placeId
  })
    .then((bar) => {
      if(bar){
        owner.bar = bar; //1
        return owner;
      }else{
        // return should do the magic
        return barCtrl.saveBar(req.body.name, req.body.placeId, req.body.longitude, req.body.latitude)
        .then((savedBar) => {
          owner.bar = savedBar; //3
          return owner;
        })
        .catch(e => {return Promise.reject(err) })
      }
    }).then(() => {
      owner.save()
        .then(savedOwner => res.json(savedOwner)) //2
        .catch(e => next(e));
    })
    .catch(e => next(e));
}

, когда вы возвращаете что-то в обещании, оно возвращается как обещание.и чтобы связать обещание, ваше текущее обещание должно вернуть обещание.который ты где не делаешь

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

Вы можете упростить многое, используя цепочку обещаний:

function setMyBar(req, res, next) {
  Bar.findOne({
    placeId: req.body.placeId
  }).then(bar => {
    if (bar) {
      return bar;
    } else {
      return barCtrl.saveBar(req.body.name, req.body.placeId, req.body.longitude, req.body.latitude);
    }
  }).then(savedBar => {
    const owner = req.queryOwner;
    owner.bar = savedBar;
    return owner.save();
  }).then(savedOwner => {
    res.json(savedOwner);
  }, e => {
    next(e);
  });
}

Важные изменения:

  • return обещание saveBar, чтобы оно было ожидаемым ивы можете использовать его результат в следующем (внешнем) then обратном вызове
  • , поместите присваивание ownwer.bar в следующий обратный вызов и просто return bar, если запрос уже нашел его, чтобы избежать дублирования кода
  • Брось бессмысленно .catch(e => {return Promise.reject(err) })
0 голосов
/ 28 мая 2018

Вам необходимо вернуть обещание в первом then() в состоянии else.Сейчас ничего не возвращается, поэтому он переходит к следующему then до того, как barCtrl.saveBar() когда-либо разрешится

Попробуйте

 Bar.findOne({
    placeId: req.body.placeId
  })
    .then((bar) => {
      if(bar){
        owner.bar = bar; //1
        return owner;
      }else{
       // return this promise
       return barCtrl.saveBar(req.body.name, req.body.placeId, req.body.longitude, req.body.latitude)
        .then((savedBar) => {
          owner.bar = savedBar; //3
          return owner;
        })
        .catch(e => {return Promise.reject(err) })
      }
    }).then(() => {
      owner.save()
        .then(savedOwner => res.json(savedOwner)) //2
        .catch(e => next(e));
    })
    .catch(e => next(e));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...