Обещание в ожидании

Мой код:

let AuthUser = data => {
  return google.login(data.username, data.password).then(token => { return token } )
}

И когда я пытаюсь запустить что-то вроде этого:

let userToken = AuthUser(data)
console.log(userToken)

Я собираюсь:

Promise { <pending> }

Но почему?

Моя главная цель - получить токен от google.login(data.username, data.password) который возвращает обещание в переменную. И только потом преформует некоторые действия.

9 ответов

Решение

Обещание всегда будет регистрироваться в ожидании, пока его результаты еще не решены. Независимо от состояния обещания (решено или еще не завершено) вы должны позвонить .then на обещание зафиксировать результаты:

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = AuthUser(data)
console.log(userToken) // Promise { <pending> }

userToken.then(function(result) {
   console.log(result) //will log results.
})

это почему?

Обещания только в прямом направлении, вы можете разрешить их только один раз, и вы можете только передать их значение их .then или же .catch методы

подробности

Согласно спецификации Promises/A+:

Процедура разрешения обещания - это абстрактная операция, принимающая в качестве входных данных обещание и значение, которое мы обозначаем как [[Resolve]](обещание, x). Если x является правдоподобным, он пытается заставить обещание принять состояние x при условии, что x ведет себя, по крайней мере, несколько как обещание. В противном случае он выполняет обещание со значением х.

Такое обращение с последующими объектами позволяет реализациям обещаний взаимодействовать, если они предоставляют способ, соответствующий Promises/A+, а затем метод. Это также позволяет реализациям Promises/A+ "ассимилировать" несовместимые реализации разумными методами then.

Эту спецификацию немного сложно разобрать, поэтому давайте разберемся с ней:

Правило таково, если функция в .then обработчик возвращает значение, Promise разрешается с этим значением. Если функция возвращает Promise следующий пункт затем будет .then разрешенного состояния возвращенного Promise, Как это на самом деле работает, более подробно описано ниже:

1. Возвращение .then функция будет значением разрешения обещания.

function initPromise() {
  return new Promise(function(res,rej) {
    res("initResolve");
  })
}

initPromise().then(function(result) {
    console.log(result); // "initResolve"
    return "normalReturn";
})
.then(function(result) {
    console.log(result); // "normalReturn"
});

2. Если .then функция возвращает обещание, тогда решение его обещания будет решением его следующего .then в принципе.

function initPromise() {
  return new Promise(function(res,rej) {
    res("initResolve");
  })
}
initPromise().then(function(result) {
    console.log(result); // "initResolve"
    return new Promise(function(resolve, reject) {
       setTimeout(function() {
          resolve("secondPromise");
       }, 1000)
   })
})
.then(function(result) {
    console.log(result); // "secondPromise"
});

Я знаю, что этот вопрос был задан 2 года назад, но я столкнулся с той же проблемой, и ответ на эту проблему с ES6, что вы можете просто await функции возвращают значение, например:

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = await AuthUser(data)
console.log(userToken) // your data

If that situation happens for a multiple values like an array.

      [ 
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> }
]

You can use Promise.all() this will resolve all promises.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

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

Так зовет AuthUser не будет внезапно входить в систему пользователя синхронно, но возвращает обещание, чьи тогда зарегистрированные обработчики будут вызваны после успешного входа (или неудачного входа). Я бы посоветовал запустить всю обработку входа в систему then пункт обещания входа в систему. Например, используя именованные функции, чтобы выделить последовательность потока:

let AuthUser = data => {   // just the login promise
  return google.login(data.username, data.password);
};

AuthUser(data).then( processLogin).catch(loginFail);

function processLogin( token) {
      // do logged in stuff:
      // enable, initiate, or do things after login
}
function loginFail( err) {
      console.log("login failed: " + err);
}

Смотрите раздел MDN об обещаниях. В частности, посмотрите на тип возвращаемого значения then ().

Для входа в систему пользовательский агент должен отправить запрос на сервер и дождаться получения ответа. Поскольку полное прекращение выполнения приложения во время обхода запроса обычно приводит к плохому взаимодействию с пользователем, практически каждая функция JS, которая регистрирует вас (или выполняет любую другую форму взаимодействия с сервером), будет использовать Promise или что-то очень похожее на него., чтобы доставить результаты асинхронно.

Теперь также обратите внимание, что return операторы всегда оцениваются в контексте функции, в которой они появляются. Итак, когда вы написали:

let AuthUser = data => {
  return google
    .login(data.username, data.password)
    .then( token => {
      return token;
    });
};

заявление return token; означало, что анонимная функция передается в then() должен вернуть токен, а не AuthUser Функция должна. Какие AuthUser возврат является результатом вызова google.login(username, password).then(callback);, который оказывается обещанием.

В конечном итоге ваш обратный звонок token => { return token; } ничего не делает; вместо этого, ваш вклад в then() должна быть функция, которая на самом деле обрабатывает токен в некотором роде.

Ваше обещание ожидается, завершите его

userToken.then(function(result){
console.log(result)
})

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

У меня была такая же проблема раньше, но моя ситуация была немного другой в интерфейсе. Я все равно поделюсь своим сценарием, может кому-то он пригодится.

У меня был вызов API /api/user/registerв интерфейсе с адресом электронной почты, паролем и именем пользователя в качестве тела запроса. При отправке формы (форма регистрации) вызывается функция-обработчик, которая инициирует вызов выборки для/api/user/register. Я использовалevent.preventDefault() в начальной строке этой функции-обработчика все остальные строки, такие как формирование тела запроса, а также вызов выборки были написаны после event.preventDefault(). Это вернулоpending promise.

Но когда я помещаю код формирования тела запроса над event.preventDefault(), он вернул настоящее обещание. Как это:

event.preventDefault();
    const data = {
        'email': email,
        'password': password
    }
    fetch(...)
     ...

вместо того:

     const data = {
            'email': email,
            'password': password
        }
     event.preventDefault();
     fetch(...)
     ...

В моем случае (JS) я забыл добавить ожидание

Попробуй это

Другие вопросы по тегам