Я не могу получить значение "результата" в Node.js

В моем console.log(info)Я хочу получить значение "результат". Но когда я использую console.log(info), Я получил Promise { <pending> }:

var info=new Promise((resolve, reject) => {
  request(options, (err, res, body) => {
    if (body.match('success') || body.match('code="25"')) {
      resolve("success");
    } else {
      reject(body);
    }
  });
}).then(result => {           
  return result;
}).catch(err => {
  console.log("error: " + err)
});

console.log(info);

Я хотел бы получить info == result, Как мне это сделать?

Спасибо

2 ответа

Решение

Что здесь происходит

Сначала немного объяснения того, что здесь происходит. Когда вы делаете что-то вроде этого:

var info = new Promise((resolve, reject) => {
  // ...
}).then(result => {
  // ...
}).catch(err => {
  // ...
});

то, что заканчивается как значение info переменная - это обещание. Это потому, что вы начинаете с обещания, возвращенного new Promise() конструктор, вы вызываете его .then() метод, который возвращает второе обещание, и на этом втором обещании вы вызываете .catch() метод, который возвращает третье обещание - и это третье обещание - это то, что сохраняется в info переменная.

Все эти вызовы методов возвращаются непосредственно перед завершением исходного HTTP-запроса, поэтому при переходе к следующей строке:

console.log(info);

невозможно получить доступ к значению ответа от request() звоните, потому что это еще не произошло (request() обратный вызов еще не был вызван на данный момент). info Переменная имеет обещание, которое является объектом, который вы можете использовать для регистрации обратных вызовов, которые вы хотите запустить, когда значение в конце концов станет доступным. Когда вы передаете его console.log() это печатает, что это обещание.

Как получить значение

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

info.then((value) => {
  // you can use the value here
  console.log('Value:', value);
}).catch((err) => {
  // the promise got rejected
  console.log('Error:', err);
});

Если вы используете относительно новую версию Node (7.0+), вы можете использовать await если вы находитесь внутри функции, объявленной с async ключевое слово, чтобы получить значение разрешения обещания следующим образом:

(async function () {

  let value = await info;
  console.log(value);

})();

или короче:

(async () => {

  console.log(await info);

})();

(Если вы уже внутри async функция тогда вам не нужна (async () => { ... })(); обертка.)

Как это устроено

Что за await Ключевое слово делает то, что возвращает обещание из неявной функции генератора, которая передает управление внешнему управляющему коду сопрограммы, который присоединяет обработчики разрешения и отклонения к этому полученному обещанию и снова запускает генератор, либо возвращая разрешенное значение из await оператор или повышение исключения, если обещание было отклонено. Затем генератор может продолжить использовать возвращаемое значение и перехватить исключение, или он может позволить пузырю исключения во внешние блоки, где оно может быть перехвачено или преобразовано в отклонение неявного обещания, возвращаемого async функция, если не обрабатывается по пути.

Как вы можете использовать это

Это может показаться сложным, но с точки зрения вашего кода это позволяет вам делать такие вещи, как:

let value = await fun();

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

Помните, что await ключевое слово выдает исключение, когда рассматриваемое обещание отклоняется. Чтобы справиться с этим делом, вы можете использовать try/catch блок:

try {
  let value = await fun();
  // promise got resolved, you have value here:
  console.log('Value:', value);
} catch (error) {
  // promise got rejected, you have error here:
  console.log('Error:', error);
}

что эквивалентно этому коду без нового синтаксиса:

fun().then((value) => {
  // promise got resolved, you have value here:
  console.log('Value:', value);
}).catch((error) => {
  // promise got rejected, you have error here:
  console.log('Error:', error);
});

с основным отличием является переменной области видимости, когда вы await на несколько обещаний в одном try блок в отличие от использования нескольких цепочек .then() обработчики, каждый из которых возвращает новое обещание.

Ваш код выглядел так, как он использовал await но это не так

Я добавил пример того, как исправить ваш код с await потому что вы написали свой код, как будто это:

var info = new Promise(...);
// here the 'info' variable is set to a promise

было действительно так:

var info = await new Promise(...);
// here the 'info' variable is set to the value
// that the promise eventually resolves to

Больше информации

Для получения дополнительной информации см.:

Поддержка узлов

Информацию о поддержке этого синтаксиса в версиях Node смотрите:

В местах, где у вас нет собственной поддержки async а также await Вы можете использовать Babel:

или с немного другим синтаксисом подход на основе генератора, как в co или сопрограммы Bluebird:

В вашем коде info это обещание. Таким образом, вы не сравниваете info ни к чему. Чтобы получить доступ к результату в обещании, вы используете .then() на обещание как в:

info.then(result => {
    // test result here
}).catch(err => {
    // handle error here
});

Кроме того, ваш .catch() Обработчик "ест" ошибку после ее регистрации. Если вы не сбросили ошибку или не вернули отклоненное обещание от .catch() обработчик, то ошибка считается "обработанной", и состояние обещания изменяется на выполненное.

Итак, вы можете сделать это:

let info = new Promise((resolve, reject) => {

    request(options, (err, res, body) => {
        if (body.match('success') || body.match('code="25"')) {
            resolve("success");
        } else {
            reject(body);
        }
    });
}).catch(err => {
    console.log("error: " + err);
    // rethrow error so promise stays rejected
    throw err;
});

info.then(result => {
    // test result here
}).catch(err => {
    // handle error here
});
Другие вопросы по тегам