Мой код:

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

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

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

Получаю:

Promise {  }

Но почему?

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

Src

Ответов: 8

Ответы (8)

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

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

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

userToken.then(function(result) {
   console.log(result) // "Some User token"
})

Почему?

Обещания действуют только в прямом направлении; Вы можете решить их только один раз. Разрешенное значение Promise передается его методам . Затем или .catch.

Подробности

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

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

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

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

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

Как это работает на самом деле более подробно описано ниже:

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

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 возвращает Promise, то разрешенное значение этого связанного обещания передается в следующий .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"
  });

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

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

Now, also notice that return statements are always evaluated in the context of the function they appear in. So when you wrote:

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

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

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

Если такая ситуация возникает для нескольких значений, таких как массив.

[
  Обещание {<ожидает>},
  Обещание {<ожидает>},
  Обещание {<ожидает>},
  Обещание {<ожидает>},
  Обещание {<ожидание>}
]

Вы можете использовать Promise.all (), это разрешит все обещания.

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

Попробуйте это

var number1 = document.getElementById ("number1");
var number2 = document.getElementById ("число2");
startAsync.addEventListener ("клик", function () {
    if (number1.value> 0 && number2.value> 0) {
        asyncTest (parseInt (number1.value), parseInt (number2.value)). then (function (result) {
            document.getElementById ("promResolved"). textContent = "promResolved:" + результат
        });
    } еще {
        asyncTest (1, 2) .then (функция (результат) {
            document.getElementById ("promResolved"). textContent = "promResolved:" + результат
        });
    }

});

асинхронная функция asyncTest (a, b) {
    вернуть ожидание (a + b);
};
  



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

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

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

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

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

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

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

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

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);
}

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

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

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

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

вместо:

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

2022 WebDevInsider