Возврат запроса как неопределенный с использованием knex - PullRequest
0 голосов
/ 07 ноября 2019

Мне нужно зарегистрировать нового пользователя, при получении параметров сделать запрос, используя название города, чтобы получить штат и идентификатор города (оба являются внешними ключами). Я реализовал функцию, чтобы найти идентификаторы. Внутри функции с использованием data.id идентификатор возвращается правильно. Но во время вставки в базу данных вставляется «undefined».

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

поток выполнения

cidade = city, estado = city

module.exports = app => {
    const obterHash = (senha, callback) => {
        bcrypt.genSalt(10, (err, salt) => {
            bcrypt.hash(senha, salt, null, (err, hash) => callback(hash))
        })
    }
    var idCidade;
    var idEstado
    function findCidade(cidade, ) {
        app.db('cidades')
        .where({ nome: cidade })
        .first()
        .then(data => {
            idCidade = data.id
            console.log('inside findCity. data.id: '+data.id)
        }).catch((err) => console.log("erro cidade", err));
    return
    }

    function findEstado(uf) {
        app.db('estados')
        .where({ uf: uf })
        .first()
        .then(data => {
            idEstado = data.id
            console.log('inside findState. data.id: '+data.id)
        }).catch((err) => console.log("erro estado", err));
    }

    const save = (req, res) => {
        console.log("\n")
        findCidade(req.body.cidade)
        findEstado(req.body.uf)

        obterHash(req.body.senha, hash => {
            const senha = hash
            console.log("Will be inserted. idCity: "+idCidade+" idState: "+idEstado)
            app.db('salao')
                .insert({ idcidade: idCidade,
                          idestado: idEstado,
                          senha})
                .then(_ => res.status(200).send())
                .catch(err =>{res.status(400).json(err)})

        })
    }
    return { save }
}

Я из Бразилии и использую переводчик, извините за орфографические ошибки.

1 Ответ

0 голосов
/ 07 ноября 2019

Добро пожаловать в асинхронный мир!

Общее объяснение: Вы собираетесь использовать результаты запросов к базе данных, прежде чем это произойдет. Ваша программа должна дождаться результатов (idCidade, idEstado), прежде чем вы сможете ее использовать. Из-за этого вы можете сначала найти запись Will be inserted... в своих журналах.

Для объяснения я собираюсь использовать Минимальный воспроизводимый пример .

function findCidade(cidade) {
  return Promise.resolve(1);
}

function findEstado(uf) {
  return Promise.resolve(1);
}

Promise.all([findCidade(), findEstado()])
  .then((data) => console.log(data));

Вывод:

[ 1, 1 ]

Чтобы решить эту проблему, вы должны:

  1. Явно вернуть обещание с помощью оператора return.
  2. Awaitрезультаты по async/await или Promise интерфейсным методам. Или используйте callbacks, если он вам больше подходит.
module.exports = app => {
  const obterHash = (senha, callback) => {
    bcrypt.genSalt(10, (err, salt) => {
      bcrypt.hash(senha, salt, null, (err, hash) => callback(hash))
    })
  };

  function findCidade(cidade, ) {
    return app.db('cidades')
      .where({ nome: cidade })
      .first()
      .then(data => {
        idCidade = data.id
        console.log('inside findCity. data.id: '+data.id)
      }).catch((err) => console.log("erro cidade", err));
  }

  function findEstado(uf) {
    return app.db('estados')
      .where({ uf: uf })
      .first()
      .then(data => {
        idEstado = data.id
        console.log('inside findState. data.id: '+data.id)
      }).catch((err) => console.log("erro estado", err));
  }

  const save = (req, res) => {
    console.log("\n");

    Promise.all([findCidade(req.body.cidade), findEstado(req.body.uf)])
      .then((data) => {
        const [idCidade, idEstado] = data;
        obterHash(req.body.senha, hash => {
          const senha = hash;

          console.log("Will be inserted. idCity: "+idCidade+" idState: "+idEstado);
          app.db('salao')
            .insert({ idcidade: idCidade,
              idestado: idEstado,
              senha})
            .then(_ => res.status(200).send())
            .catch(err =>{res.status(400).json(err)})

        })
      })
      .catch((err) => console.log("general error", err));
  };
  return { save }
}
...