как получить ценность от выполненного обещания в реакции

У меня есть API, который возвращает мои ожидаемые результаты в проекте реагирования.

Я написал эту функцию для вызова API и получения результатов:

async function getUsers() {
  const token = store.getState().token;
  const data = { token };
  await MyApi.getUsers(data)
    .then((result) => {
      console.log(result);
      return result;
    })
    .catch((error) => {
      console.log(error);
      return null;
    });
}

const userList = getUsers();

Когда я console.log result в разделе then функции, он напечатал ожидаемый список пользователей (это массив json). Но когда я console.log userList это promise как показано ниже:

введите здесь описание изображения

это означает, что возвращаемое значение функции getUsers равно Promise.

1- Как я могу получить результаты от этого обещания?

2- почему PromiseResult - это undefined, а result в разделе then - это массив json?

** этих кодов нет в реагирующем компоненте

ожидаемый result:

[
 {
  id: 1,
  name: "user1",
  role: "student"
 },
{
  id: 2,
  name: "user2",
  role: "student"
 },
{
  id: 3,
  name: "user3",
  role: "student"
 },
]

и я хочу использовать массив userList для создания user card:

<div>
{userList ? (
 userList.map((user) =>
 {
  <Card>
    <h1> user.name </h1>
  </Card>
 }
):
(<h1>user list is empty </h1>)
}

person Zahra Talebi    schedule 15.02.2021    source источник
comment
getUsers — это функция async, она неявно возвращает обещание. Если вам нужно разрешенное значение, вы должны await его или .then из него, то есть getusers().then(userList => ....).   -  person Drew Reese    schedule 15.02.2021
comment
Не могли бы вы объяснить, как я могу назначить result функции getUsers функции UserList? Я на самом деле новичок в JS и реагирую   -  person Zahra Talebi    schedule 15.02.2021
comment
Я думал, что уже сделал, исходя из ограниченного объема вашего фрагмента. Можете ли вы предоставить более минимальный, полный и воспроизводимый пример того, как вы пытаетесь использовать разрешенное значение?   -  person Drew Reese    schedule 15.02.2021


Ответы (3)


Проблема

почему PromiseResult не определен, а результат в разделе then представляет собой массив json?

getUsers — это функция async, поэтому она неявно возвращает Promise, но вы не возвращаете никакого разрешенного значения, она просто ожидает разрешения обещания MyApi.getUsers и ничего не возвращает, т. е. возвращает void или undefined.

Другими словами, логически это выглядит примерно так:

async function getUsers() {
  const token = store.getState().token;
  const data = { token };
  await MyApi.getUsers(data)
    .then((result) => {
      console.log(result);
      return result;
    })
    .catch((error) => {
      console.log(error);
      return null;
    });
  return undefined;
}

Решение

Верните обещание MyApi.getUsers.

async function getUsers() {
  const token = store.getState().token;
  const data = { token };
  return MyApi.getUsers(data)
    .then((result) => {
      console.log(result);
      return result;
    })
    .catch((error) => {
      console.log(error);
      return null;
    });
}

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

const [userList, setUserList] = useState([]);

useEffect(() => {
  getusers()
    .then(userList => setUserList(userList))
    .catch(error => {
      // handle any error state, rejected promises, etc..
    });
}, []);

Or

const [userList, setUserList] = useState([]);

useEffect(() => {
  const loadUserList = async () => {
    try {
      const userList = await getusers();
      setUserList(userList)
    } catch(error) {
      // handle any error state, rejected promises, etc..
    }
  };

  loadUserList();
}, []);
person Drew Reese    schedule 15.02.2021
comment
в вашем последнем примере есть ли конкретная причина, по которой loadUserList не является всей функцией, переданной useEffect? Создание и назначение функции переменной, а затем вызов ее здесь кажется ненужным.... - person Garrett Motzner; 16.02.2021
comment
@GarrettMotzner Здесь это совершенно необходимо. Поскольку обратные вызовы хука React на 100% синхронны, для await любых значений мы должны создать асинхронную функцию и вызвать ее, тогда эта функция может await использовать любой другой асинхронный код. Это обычная схема. Определение его внутри обратного вызова эффекта также удаляет его как зависимость эффекта. Другими словами, useEffect(async () => { ..... }, [.......]); недействителен и не работает. - person Drew Reese; 16.02.2021
comment
Но если вы измените последнюю строку на return loadUserList(), разве у вас не будет той же функции async, что и useEffect(async () => { ..... }, [.......]);? AFAIK, асинхронная функция, функция синхронизации, которая возвращает обещание, поэтому, если вас не волнует возвращаемое значение, нет причин, по которым вы не можете использовать асинхронную функцию вместо функции синхронизации... - person Garrett Motzner; 16.02.2021
comment
@GarrettMotzner Не совсем так. Единственное, что вы возвращаете из обратного вызова ловушки useEffect, — это функция очистки, которая должна быть вызвана, когда компонент собирается повторно отобразить или размонтировать. Возврат асинхронной функции loadUserList Promise вызовет проблему. - person Drew Reese; 16.02.2021
comment
Понятно. Я забыл, что возвращаемое значение обратного вызова ловушки обычно было обратным вызовом очистки. Тогда это имеет смысл, поскольку асинхронная функция не может возвращать значение синхронизации, как функция очистки. React, кажется, справляется с этим хорошо и не вызывает никаких ошибок, но имеет смысл не делать это шаблоном. - person Garrett Motzner; 16.02.2021

Почему вы получаете обещание {ожидание}? Обещание всегда будет логироваться в ожидании, пока его результаты еще не разрешены. Таким образом, вы должны вызвать .then(), чтобы зафиксировать результаты. Если функция в обработчике .then() возвращает значение, то Promise разрешается с этим значением в userList, однако в вашем случае .then() возвращает другое обещание, поэтому следующий обработчик .then() всегда будет содержать значение вы хотите получить.

async function getUsers() {
  const token = store.getState().token;
  const data = { token };
  await MyApi.getUsers(data)
    .then((result) => {
      console.log(result);
      return result;
    })
    .catch((error) => {
      console.log(error);
      return null;
    });
}

const userList =getUsers();
console.log(userList ); // Promise  <pending> 
userList.then((result)=> {
console.log(result) // "Some desired value"
})

другой вариант - просто добавить await getUsers()

async function getUsers() {
  const token = store.getState().token;
  const data = { token };
  await MyApi.getUsers(data)
    .then((result) => {
      console.log(result);
      return result;
    })
    .catch((error) => {
      console.log(error);
      return null;
    });
}

const userList =await getUsers();
console.log(userList ); // "Some desired value"
person yairmea    schedule 15.02.2021

Вот фрагмент кода, который может помочь вам лучше понять его

//Api response simulation
function fetchUsers() 
{
return Promise.resolve({'name' :'tom'});
}

//async will always return promise
async function getUsers() { 
  const response = await fetchUsers();
  return response;
}

getUsers().then((users) => console.log(users)
 // here you can fill the usersList 
 );

и я думаю, что чтение этой ссылки поможет вам глубоко понять асинхронное ожидание https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await

person Mohammed Said Elattar    schedule 15.02.2021