Ожидание обещания разрешить из родительской функции - PullRequest
1 голос
/ 07 июня 2019

У меня есть основной поток в моем приложении узла, такой как это:

function main_thread() {
  console.log("Starting");
  values = get_values(1);
  console.log(values);
  console.log("I expect to be after the values");
}

Функция get_values вызывает функцию hgetall с использованием пакета node_redis . Эта функция обеспечивает обратный вызов, но может быть обещана:

function get_values(customer_id) {
  // Uses a callback for result
  new Promise(function(resolve, reject) {
    redis_client.hgetall(customer_id, function (err, result) {
    if (err) console.log(err)
      console.log("About to resolve");
      resolve(result);
    });
  })
  .then(({result}) => {
    console.log(result);
  });
}

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

Вот как я это сделаю на ruby, основном языке, который я использую:

def get_values(customer_id)
  return @redis_client.hgetall(customer_id)
end

Как создать обещание в многократно используемой функции и заставить главный поток ждать, пока функция не вернет ответ от обещания?

EDIT:

Было высказано предположение, что обещание может быть возвращено с then в основной цепочке. Однако это все еще означает, что любой код в основном потоке после того, как вызов функции выполняется перед блоком then.

РЕДАКТИРОВАТЬ 2:

После продолжительного обсуждения с некоторыми друзьями-разработчиками IRL JS похоже, что попытка создать синхронный скрипт противоречит идеалу современного JS. Я собираюсь вернуться к дизайну своего приложения и работать над его асинхронностью.

Ответы [ 3 ]

2 голосов
/ 07 июня 2019

Просто, как возвращение обещания (цепочки) из вашей функции

function get_values(customer_id) {
  // Uses a callback for result
  return new Promise(function(resolve, reject) {
    redis_client.hgetall(customer_id, function (err, result) {
    if (err) console.log(err)
      console.log("About to resolve");
      resolve(result);
    });
  })
  .then(({result}) => {
    console.log(result);
  });
}

А потом в вашем основном async function или function

let result = await get_values(); или get_values.then(function(result){})

function main_thread() {
  console.log("Starting");
  values = get_values(1).then(function(values){
    console.log(values);
    console.log("I expect to be after the values");
  });
}

async function main_thread() {
  console.log("Starting");
  let values = await get_values(1);
  console.log(values);
  console.log("I expect to be after the values");
}
1 голос
/ 07 июня 2019

Вот рабочий пример с async / await. Я заменил redis тайм-аутом и массивом для данных.

async function main_thread() {
  console.log("Starting");
  values = await get_values(1);
  console.log(`After await: ${values}`);
  console.log("I expect to be after the values");
}

async function get_values(customer_id) {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
        const result = [1, 2, 3];
        console.log(`Resolving: ${result}`);
        resolve(result);
      }, 300);
  });
}

main_thread();

Дополнительная информация:

1 голос
/ 07 июня 2019

Верните обещание в get_values

function get_values(customer_id) {
  // Uses a callback for result
  return new Promise(function(resolve, reject) {
    redis_client.hgetall(customer_id, function (err, result) {
    if (err) console.log(err)
      console.log("About to resolve");
      resolve(result);
    });
  })
  .then(({result}) => {
   reject(result);
  });
}

Теперь в вашей основной теме вы можете подождать его, например:

function main_thread() {
  console.log("Starting");
  get_values(1).then(function(values) {
    console.log(values);
  }).catch(function(error) {
    console.error(error);
  });
}
...