You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在循环内调用AsyncStorage.setItem导致应用崩溃如何解决?

问题现象

React Native开发中调用AsyncStorage存储数据时,应用无提示崩溃,仅函数入口的console.log("ran")可正常输出,循环内的日志完全没有打印,崩溃逻辑通过Pressable组件的onPress事件触发。
问题代码如下:

const saving = () => {
  console.log("ran") // 可正常执行
  let loop = true
  let cont = 0
  while (loop == true) {
    console.log("got here") // 完全没触发
    AsyncStorage.getItem(`Item-${cont}`, (error, result) => {
      console.log("here")
      if (error) {
        Toast.show({
          type: 'error',
          text1: 'An error has ocurred!'
        })
        loop = false
      } else if (result == null) {
        AsyncStorage.setItem(`Item-${cont}`, (error) => {
          console.log("there")
          if (error) {
            Toast.show({
              type: 'error',
              text1: 'Error occurred while saving workout!'
            })
            loop = false
          } else {
            Toast.show({
              type: 'success',
              text1: 'Workout saved successfully!'
            })
            loop = false
          }
        })
      }
    })
    cont++
  }
}
<Pressable
  onPress={() => saving()}
>

</Pressable>
崩溃根因
  • 核心问题是同步while死循环完全堵死JS单线程:JS运行时是单线程模型,AsyncStorage的读写回调属于异步任务,必须等当前所有同步代码执行完毕才会被调度执行。也就是说while循环启动后,回调里修改loop = false的逻辑永远没有执行机会,cont变量会无限自增,瞬间占满内存导致应用直接崩溃,没有报错是因为崩溃速度太快,错误捕获、日志输出逻辑都没来得及触发。
  • 看不到console.log("got here")的打印不是代码没进入循环,是死循环占满了全部线程资源,console的日志还没来得及通过React Native的调试桥传输到控制台,程序就已经终止了。
  • 代码存在显性参数错误:AsyncStorage.setItem的标准调用签名是setItem(键名, 待存储的字符串值, 回调函数),当前代码只传了键名和回调,缺少必填的存储值参数,就算循环不卡死,走到这行也会抛出异常。
修复方案

不要用同步循环等待异步回调,直接用async/await改写逻辑,按顺序查找空的存储位,找到后写入数据再退出循环即可:

import AsyncStorage from '@react-native-async-storage/async-storage';

const saving = async () => {
  console.log("ran")
  let cont = 0
  while (true) {
    const storageKey = `Item-${cont}`
    try {
      const existResult = await AsyncStorage.getItem(storageKey)
      if (existResult === null) {
        // 下方第二个参数替换为你实际要存储的内容,注意AsyncStorage仅支持字符串类型,对象需要提前JSON.stringify序列化
        await AsyncStorage.setItem(storageKey, JSON.stringify({
          // 替换为实际要存的训练数据
        }))
        Toast.show({
          type: 'success',
          text1: '训练保存成功!'
        })
        break
      }
      cont++
    } catch (err) {
      Toast.show({
        type: 'error',
        text1: '保存失败,请重试!'
      })
      break
    }
  }
}

Pressable的绑定逻辑无需额外修改,也可以简写成onPress={saving}。

  • 优化提示:如果后续存储的条目越来越多,每次从0开始遍历找空key会越来越慢,可以单独维护一个ItemTotalCount的存储键,每次保存时直接读取这个计数值拼接key,存完数据后把计数值+1写回存储,省去遍历的开销。

内容的提问来源于stack exchange,提问作者hrodric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 00:12:29