代码之家  ›  专栏  ›  技术社区  ›  geoffjay

异步存储抱怨在合并项期间数组和对象不兼容

  •  2
  • geoffjay  · 技术社区  · 6 年前

    我想知道为什么 AsyncStorage 在一个反作用的本地应用程序中,拒绝执行 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]
    

    这让人困惑,因为当数据打印出来时,它是一个 {...} 但是 异步存储 显示一个数组 [...] . 我有什么东西不见了吗?这对我来说似乎很愚蠢,我似乎不知道如何让RN表现得很好。

    在我看来,数据的结构很粗糙,但这正是我的工作。我没有决定,也不能改变。

    2 回复  |  直到 6 年前
        1
  •  1
  •   agm1984    6 年前

    我记得和 AsyncStorage 它与 localStorage 因为它回报承诺。

    你的代码看起来很好,这让我非常困惑,但是我突然怀疑这个问题可能是由于丢失了 await 关键字。

    尝试:

    .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. 没有 对于返回承诺的函数

    3. 解释器不等待它解析,并立即移动到下一行代码。

    4. 没有下一行代码,因此它从 then() 0.1毫秒后阻塞(请记住它是隐式执行的 return undefined 异步函数内部的 resolve(undefined) ,重点是它正在尝试解决整个链的备份 await AsyncStorage.getItem(THINGS_STORAGE_KEY)

    5. obj 垃圾收集0.1毫秒后

    6. 异步存储.mergeitem() 观察一个不稳定的值 OBJ 但我不确定。它可能不执行步骤5或6,而是检测到 mergeItem 当它尝试解决 getItem 链条,无论哪种方式:

    7. 然后,AsyncStorage给出了一个令人困惑的错误消息

        2
  •  1
  •   geoffjay    6 年前

    我最终用来正确处理承诺的是:

    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() 除了那个电话,那看起来和我做的完全一样。这可能也是值得尝试的,但这对我很有用。