AsyncStorage 在 mergeItem 期间抱怨数组和对象不兼容
AsyncStorage complains of array and object incompatibility during mergeItem
我想弄清楚为什么 React Native 应用程序中的 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]
这很令人困惑,因为当数据打印出来时它是一个带有 {...}
的对象,但是 AsyncStorage
显示一个带有 [...]
的数组。有什么我想念的吗?这对我来说似乎很愚蠢,我似乎无法弄清楚如何让 RN 打得很好。
PS。 IMO 的数据结构很粗糙,但这正是我正在使用的。这不是我决定的,我也无法改变。
我记得曾使用 AsyncStorage
,它与 localStorage
有根本的不同,因为它 returns 承诺。
你的代码看起来很好,这让这非常混乱,但我突然怀疑问题可能是由于缺少 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))
})
这可能是一个经典的 "not waiting for the Promise to resolve" 在继续之前,异步问题。如果是这样,请不要删除此问题。将来对包括我自己在内的其他人都有帮助。
这是我认为正在发生的事情:
JavaScript 将 AsyncStorage.mergeItem()
抛入函数队列
没有await
这个函数returns一个Promise
解释器不等待它解析并立即移动到下一行代码
没有下一行代码,所以它在 0.1 毫秒后从 then()
块 returns(请记住,它隐含地执行 return undefined
异步函数内部与 resolve(undefined)
相同,关键是它试图将整个链解析回 await AsyncStorage.getItem(THINGS_STORAGE_KEY)
obj
之后 0.1 毫秒收集垃圾
AsyncStorage.mergeItem()
在预期 obj
的地方观察到一个虚假值,但我实际上并不确定。它可能没有执行第 5 步或第 6 步,而是在尝试解析 getItem
链时检测到 mergeItem
仍未决,无论哪种方式:
AsyncStorage 然后给出一个令人困惑的错误消息
我最终用来正确处理 promise 的是:
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()
的类似示例,除了那个调用之外,它们看起来与我所做的完全相同。这可能也值得尝试,但这对我有用。
我想弄清楚为什么 React Native 应用程序中的 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]
这很令人困惑,因为当数据打印出来时它是一个带有 {...}
的对象,但是 AsyncStorage
显示一个带有 [...]
的数组。有什么我想念的吗?这对我来说似乎很愚蠢,我似乎无法弄清楚如何让 RN 打得很好。
PS。 IMO 的数据结构很粗糙,但这正是我正在使用的。这不是我决定的,我也无法改变。
我记得曾使用 AsyncStorage
,它与 localStorage
有根本的不同,因为它 returns 承诺。
你的代码看起来很好,这让这非常混乱,但我突然怀疑问题可能是由于缺少 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))
})
这可能是一个经典的 "not waiting for the Promise to resolve" 在继续之前,异步问题。如果是这样,请不要删除此问题。将来对包括我自己在内的其他人都有帮助。
这是我认为正在发生的事情:
JavaScript 将
AsyncStorage.mergeItem()
抛入函数队列没有
await
这个函数returns一个Promise解释器不等待它解析并立即移动到下一行代码
没有下一行代码,所以它在 0.1 毫秒后从
then()
块 returns(请记住,它隐含地执行return undefined
异步函数内部与resolve(undefined)
相同,关键是它试图将整个链解析回await AsyncStorage.getItem(THINGS_STORAGE_KEY)
obj
之后 0.1 毫秒收集垃圾AsyncStorage.mergeItem()
在预期obj
的地方观察到一个虚假值,但我实际上并不确定。它可能没有执行第 5 步或第 6 步,而是在尝试解析getItem
链时检测到mergeItem
仍未决,无论哪种方式:AsyncStorage 然后给出一个令人困惑的错误消息
我最终用来正确处理 promise 的是:
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()
的类似示例,除了那个调用之外,它们看起来与我所做的完全相同。这可能也值得尝试,但这对我有用。