localStorage在Vue mounted生命周期和异步函数中的读取行为分析?

localStorage.getItem('test')已存在,从A应用调到B应用时的时机(域名都相同):
想知道异步函数中localStorage.getItem('test')的值在mounted生命周期为什么取不到,代码如下:

mounted() {
  this.init()
},
methods: {
  async init() {
      console.log(localStorage.getItem('test')) // 此时能取到值
      const data = await request(xxx) // 发起某个请求的函数
      console.log(localStorage.getItem('test')) // 此时反而取不到值
  }
}

通过的尝试:定时器0.5s后调用init方法能获取test数据,感觉是队列的问题?
想知道:
1、localStorage第一次进入网页的读取方式
2、为什么获取不到test,具体的队列是怎么执行的

阅读 1.4k
avatarAI BotBETA
### 回答

1. **localStorage第一次进入网页的读取方式**

   localStorage 是一种在客户端存储数据的方式,它允许你存储键值对,并且这些数据在页面重新加载后依然存在。当你第一次进入网页时,如果 localStorage 中已经存储了某些数据(例如 'test'),你可以通过 `localStorage.getItem('test')` 直接读取这些值。读取操作是同步的,即它会立即返回存储的值,不需要等待。

2. **为什么获取不到 'test',具体的队列是怎么执行的**

   在你提供的代码中,出现无法获取到 'test' 的情况并不是因为 localStorage 的问题,而是由于异步函数和事件循环的交互导致的误解。

   在 `mounted` 生命周期钩子中,你调用了 `this.init()` 方法,这是一个异步函数。在 `init` 方法中,首先通过 `console.log(localStorage.getItem('test'))` 打印了 localStorage 中的 'test' 值,此时由于 localStorage 是同步的,所以能够立即获取到值。

   接着,你使用 `await` 关键字调用了 `request(xxx)`,这是一个异步操作,会导致 JavaScript 运行时暂停 `init` 方法的执行,直到 `request(xxx)` 返回结果。在 `request(xxx)` 执行期间,JavaScript 运行时可能会处理其他事件或任务,包括可能由其他脚本或浏览器行为引起的 localStorage 更改(尽管在你的案例中,这种更改似乎不太可能,因为域名相同且未提及其他脚本修改 localStorage)。

   然而,更可能的原因是,你观察到的行为实际上是由于代码的其他部分或浏览器行为导致的误解。在你提到的“定时器0.5s后调用init方法能获取test数据”的情况下,这可能是由于某种形式的延迟或竞态条件导致的。定时器确保了 `init` 方法在足够的时间后执行,此时 localStorage 的状态可能已经稳定或恢复了预期的值。

   重要的是要理解,localStorage 本身没有“队列”的概念。它是同步的,并且直接反映底层存储的状态。如果在一个时间点能够读取到 'test' 的值,而在另一个时间点不能,这通常是由于在两次读取之间,localStorage 的状态被其他代码或操作更改了,或者存在某种形式的同步问题(例如,由于多线程或异步操作的时序问题)。

   在你的案例中,最合理的解释是,`request(xxx)` 的执行或其他异步操作没有直接影响 localStorage 的状态,但可能由于某种原因(如代码中的其他逻辑、浏览器行为或竞态条件)导致了看似不一致的行为。为了解决这个问题,建议仔细检查代码中的其他部分,特别是那些可能修改 localStorage 或影响异步操作时序的部分。
1 个回答

不会有问题,看上去是因为 request(xxx) 里面执行了一些业务修改了 localStorage,或者在等待期间其他的业务函数修改了 localStorage

执行顺序就是你书写的顺序执行。先输出一次 getItem('test'),然后等待 request 请求返回结果之后再输出一次 getItem('test')

<script setup>
import { ref, onMounted } from 'vue'

const msg = ref('Hello World!')
localStorage.setItem('test', 'ABCDEFG')

onMounted(() => {
  console.log('onMounted1')
  init()
  init2()
  console.log('onMounted2')
})

async function init(){
  console.log('init1-test1', localStorage.getItem('test'))
  await mockApi('init1')
  console.log('init1-test2', localStorage.getItem('test'))
}

async function init2(){
  console.log('init2-test1', localStorage.getItem('test'))
  await mockApi('init2')
  console.log('init2-test2', localStorage.getItem('test'))
}

function mockApi(str) {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(str + '-setTimeout')
      resolve('success')
    }, 1000)
  })
}

</script>
// log =>
onMounted1
init1-test1 ABCDEFG
init2-test1 ABCDEFG
onMounted2
init1-setTimeout
init1-test2 ABCDEFG
init1-setTimeout
init1-test2 ABCDEFG
init2-setTimeout
init2-test2 ABCDEFG
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题