AsyncStorage жалуется на несовместимость массивов и объектов во время mergeItem - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь выяснить, почему AsyncStorage в приложении React Native отказывается делать mergeItem с моими данными.Моя функция выглядит следующим образом:

const arrToObj = (array) =>
  array.reduce((obj, item) => {
    obj[Object.keys(item)[0]] = Object.values(item)[0]
    return obj
  }, {})

export const addThingToThing = async (title, thing) => {
  try {
    let subThings = []
    let things = {}
    await AsyncStorage.getItem(THINGS_STORAGE_KEY)
      .then((things) => {
        let subThings = []
        Object.values(JSON.parse(decks))
          .map((thing) => {
            if (Object.keys(thing)[0] === title) {
              subThings = [...Object.values(thing)[0].subThings, subThing]
            }
          })
        return { decks, subThings }
      })
      .then(({ decks, subThings }) => {
        const obj = {
          ...arrToObj(JSON.parse(things)),
          [title]: {
            subThings
          }
        }
        console.log(JSON.stringify(obj))
        AsyncStorage.mergeItem(THINGS_STORAGE_KEY,
          JSON.stringify(obj))
      })
  } catch (error) {
    console.log(`Error adding thing to thing: ${error.message}`)
  }
}

Когда я делаю то, что выполняет это, я получаю:

13:35:52: {"test":{"subThings":[{"one":"a","two":"a"}]},"test2":{"title":"test2","questions":[]}}
13:35:55: [Unhandled promise rejection: Error: Value [{"test":{"title":"test","subThings":[]}},{"test2":{"title":"test2","subThings":[]}}] of type org.json.JSONArray cannot be converted to JSONObject]

Что сбивает с толку, потому что, когда данные выводятся на печать, это объект с{...}, но AsyncStorage показывает массив с [...].Я что-то упускаю?Мне это кажется довольно глупым, и я не могу понять, как заставить RN играть хорошо.

PS.ИМО структура данных грубая, но это то, с чем я работаю.Я не принял решение, и я не могу изменить его.

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

То, что я в итоге использовал для правильной обработки обещаний:

export const addThingToThing = async (title, thing) => {
  try {
    AsyncStorage.getItem(THINGS_STORAGE_KEY, (err, things) => {
      let subThings = []
      Object.values(JSON.parse(decks))
        .map((thing) => {
          if (Object.keys(thing)[0] === title) {
            subThings = [...Object.values(thing)[0].subThings, subThing]
          }
        })
      const obj = {
        [title]: {
          title,
          subThings
        }
      }
      console.log(JSON.stringify(obj))
      AsyncStorage.mergeItem(THINGS_STORAGE_KEY,
        JSON.stringify(obj))
    })
  } catch (error) {
    console.log(`Error adding thing to thing: ${error.message}`)
  }
}

В Интернете я видел несколько других подобных примеров, в которых использовался .done(), которые выглядели идентично тому, что я делал, кроме этого звонка.Это тоже можно было попробовать, но у меня это получилось.

0 голосов
/ 27 мая 2018

Я помню, как работал с AsyncStorage, и он принципиально отличается от localStorage, потому что он возвращает Promises.

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

try:

.then(async ({ decks, subThings }) => {
  const obj = {
    ...arrToObj(JSON.parse(things)),
    [title]: {
      subThings
    }
  }
  console.log(JSON.stringify(obj))
  // We are adding await here
  await AsyncStorage.mergeItem(THINGS_STORAGE_KEY, JSON.stringify(obj))
})

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

Вот то, что я думаю, происходит:

  1. JavaScript выбрасывает AsyncStorage.mergeItem() в очередь функций

  2. Нет функции await для этой функции, которая возвращает Обещание

  3. Интерпретатор не ожидает его разрешения и сразу же переходит к следующей строкекода

  4. Следующая строка кода отсутствует, поэтому он возвращается из блока then() через 0,1 мс (имейте в виду, что он неявно выполняет return undefined, что внутри асинхронной функциито же самое, что и resolve(undefined), с тем, что он пытается разрешить всю цепочку обратно до await AsyncStorage.getItem(THINGS_STORAGE_KEY)

  5. obj получает мусор, собираемый через 0,1 мс после этого

  6. AsyncStorage.mergeItem() наблюдает ложное значение там, где ожидалось obj, но я не знаю наверняка. Возможно, он не выполняет шаг 5 или 6 и вместо этого обнаруживает это mergeItem все еще ожидает, когда он пытается разрешить цепочку getItem,в любом случае:

  7. Затем AsyncStorage выдает сбивающее с толку сообщение об ошибке

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...