当前位置: 首页 > 知识库问答 >
问题:

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

钮边浩
2025-01-17

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,具体的队列是怎么执行的

共有2个答案

阳修永
2025-01-17

不会有问题,看上去是因为 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
裴实
2025-01-17
### 回答

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 或影响异步操作时序的部分。
 类似资料:
  • 我正在阅读react lifecycle,有点困惑。有些人建议使用componentWillMount进行ajax调用: https://hashnode.com/post/why-is-it-a-bad-idea-to-call-setstate-immediately-after-componentdidmount-in-react-cim5vz8kn01flek53aqa22mby 在com

  • 忽视省略(elision)情况,带上生命周期的函数签名(function signature)有一些限制: 任何引用都必须拥有标注好的生命周期。 任何被返回的引用都必须有一个和输入量相同的生命周期或是静态类型(static)。 另外要注意,若会导致返回的引用指向无效数据,则返回不带输入量的引用是被禁止的。下面例子展示了一些带有生命周期的函数的有效形式: // 一个拥有生命周期 `'a` 的输入引用

  • 问题内容: 我正在阅读反应生命周期,并感到有些困惑。一些建议使用componentWillMount进行ajax调用: https://hashnode.com/post/why-is-it-a-bad-idea-to-call-setstate-immediately- after-componentdidmount-in-react- cim5vz8kn01flek53aqa22mby 在co

  • 本文向大家介绍react生命周期函数相关面试题,主要包含被问及react生命周期函数时的应答技巧和注意事项,需要的朋友参考一下 这个问题要考察的是组件的生命周期 一、 初始化阶段: Constructor初始化状态 componentWillMount:组件即将被装载、渲染到页面上 render:组件在这里生成虚拟的DOM节点 componentDidMount:组件真正在被装载之后 二、 运行中

  • 生成本地代码时,作为C/C++程序的入口函数,通常main()函数意味着程序的整个生命周期,程序随main()函数返回的返回而退出;而在Emscripten下,情况有所不同,来看下面的例子: //main.cc #include <stdio.h> EM_PORT_API(int) show_me_the_answer() { return 42; } int main() { print

  • 我想在maven测试期间在Java14中运行spock 2.0-M2-Groovy-3.0和junit 5.6.2测试。我的pom看起来: 如果我跑 在maven生命周期中运行spock和junit测试是否可能没有上述警告?

  • 无法在Tomcat中删除此错误。错误如下:- 请告诉我如何解决Tomcat中的生命周期异常?

  • 问题内容: 在哪里进行调用将使我的状态失水的API调用的最佳位置是哪里?构造函数或生命周期方法之一,例如ComponentWillMount? 问题答案: 最好从生命周期方法进行api调用,反应文档也建议相同。 根据DOC: componentDidMount: 挂载组件后立即调用componentDidMount()。需要DOM节点的初始化应该在这里进行。 如果需要从远程端点加载数据,这是实例化