Получить данные из обещания.Или это вообще обещание? - PullRequest
1 голос
/ 17 июня 2019

Я храню некоторые данные в IndexedDB и использую для этого пакет npm localforage.

const retrieveData = async () => {
  const keys = await localforage.keys()
  const data = await keys.map(async (key) => {
    const item = await localforage.getItem(key)
    return [item.username, item.compamy, item.email, item.lastUpdate]
  })
  return data
}

Всякий раз, когда я выполняю эту функцию, я получаю разрешенный объект Promise, значения которого я не могу извлечь

async componentDidMount() {
  let asyncData = retrieveData()
  console.log(asyncData)  // Promise object
  asyncData = retrieveData().then(values => values)
  console.log(asyncData)  // Promise object anyways
}

Как именно я должен получить данные из этого объекта Promise?

Ответы [ 3 ]

2 голосов
/ 17 июня 2019
const retrieveData = async () => {
  const keys = await localforage.keys()
  // The return value of "keys.map" is an array of promises since
  // async automatically returns a Promise behind the scenes.
  // Await works on a single promise, not an array of promises,
  // so "data" will not contain the actual data. 
  const data = await keys.map(async (key) => {
    const item = await localforage.getItem(key)
    return [item.username, item.compamy, item.email, item.lastUpdate]
  })
  return data
}

Do:

const retrieveData = async () => {
  const keys = await localforage.keys()
  const data = await Promise.all(keys.map(async (key) => {
    const item = await localforage.getItem(key)
    return [item.username, item.compamy, item.email, item.lastUpdate]
  }));
  return data
}

Или использовать карту Bluebird, которая в этом сценарии работает из коробки :

// The "then" function does not do anything. It returns values,
// but only does so to the next "then" function. There are no
// further then-functions so the return value is unused.
// "values" is merely a local variable so you won't be able to
// access it anywhere outside the fat arrow function.
// You could move the console log into "then".
asyncData = retrieveData().then(values => values) 


// asyncdata is still the unresolved promise object, the "then"
// function has not been run yet (then on the line above will be run when
// all of the awaits in retrieveData have been successfully resolved.
console.log(asyncData)  

Do:

async componentDidMount() {
  const data = await retrieveData();
  console.log(data);
}

Или:

componentDidMount() {
  retrieveData().then(values => {
    console.log(values);
  });
}
1 голос
/ 18 июня 2019

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

  const retrieveData = async () => {
  const keys = await localforage.keys()
  let data;
  for (let key of keys) {
    const item = await localforage.getItem(key);
    data.push([item.username, item.compamy, item.email, item.lastUpdate]);
  }
  return data
}
1 голос
/ 17 июня 2019

Попробуйте использовать зарезервированное ключевое слово " await " перед вашим retrieveData () методом в componentDidMount () , так как это обещание, асинхронное событие, вынужно подождать, пока он не завершит все свои внутренние исполнения, чтобы вернуть некоторые данные и продолжить.

Так же, как вы это делали при объявлении retrieveData () , используйте , ожидайте дообещаю.подробно что нужно:

async componentDidMount() {
  let asyncData = await retrieveData()
  ....
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...