【问题标题】:Changes in cache are not saved without async/await没有 async/await 就不会保存缓存中的更改
【发布时间】:2019-12-27 18:28:33
【问题描述】:

我有一个react-native 应用程序,它使用react-navigation。有一个带有按钮单击处理程序的功能组件。

我最近遇到了async/await 的问题。我在非异步方法中调用了异步方法,但它没有按预期工作。我对其进行了一点调试,发现调用了 async 方法并完成了它应该做的所有事情,但之后更改就丢失了。

非异步方法如下所示:

const handleDone = () => {
  api.events.removeEventFromCache(eventId);
  navigation.navigate(routes.Events);
};

调用该方法时,会从缓存中删除一个对象,并将用户导航到另一个屏幕。 api.events.removeEventFromCache(eventId) 被调用并成功完成,我什至检查缓存以查看对象已被删除。问题是在navigation.navigate(routes.Events) 之后它突然还在缓存中。

添加 async/await 关键字解决了问题,但我不太明白为什么:

const handleDone = async () => {
  await api.events.removeEventFromCache(eventId);
  navigation.navigate(routes.Events);
};

我虽然它会做所有事情而不等待结果但是为什么结果消失了?这不是关于执行顺序和等待结果的问题。我并不真正关心结果,我只是希望它完成。

这是没有关键字的日志:

--> in cache now 3
remove the event from cache
navigate to events
cache length before remove 3
--> in cache now 3
cache length set 2
cache length checked 2
--> in cache now 3

带有关键字的日志:

--> in cache now 3
remove the event from cache
cache length before remove 3
cache length set 2
cache length checked 2
navigate to events
--> in cache now 2

是的,执行上有区别,但我的问题是关于缓存中的结果。

【问题讨论】:

  • 异步意味着它在不同的时间做某事——异步。因此,如果您执行asyncRemoveX(); getX(),第二行仍将返回您,无论X 是什么,因为asyncRemoveX 未完成 - 它将在稍后完成。这就是 await 存在的原因 - 顾名思义,它 等待 异步函数完成,因此 await asyncRemoveX() 将保证在下一行完成。
  • Async/Await 语法本质上为您提供了一种替代方法来编写没有回调的异步代码。您的异步函数转换为:api.events.removeEventFromCache(eventId).then(navigation.navigate())
  • 我添加了日志。最后几行有不同的结果。
  • 据我了解,导航方法将缓存的副本传递给导航事件。创建副本并丢弃前一个副本。在第一种情况下,您的应用程序在仍然有事件时复制缓存并将其发送到导航功能。您的 api 方法正在编辑的缓存副本已删除您的事件,但不再使用该副本。在第二种情况下,您的导航函数接收更新的缓存。希望对您有所帮助。

标签: javascript react-native async-await react-navigation


【解决方案1】:

当您在 navigation 之前和之后记录输出时,您正在登录 2 个不同的上下文。

为了解释这一点,假设您有一个缓存对象cache,您希望从中删除事件。 不带关键字的代码执行方式如下:

  • cache由待编辑的api方法加载
  • navigation 方法执行,它会将当前cache 的副本发送到下一个屏幕并丢弃上一个屏幕。
  • cache-copynavigation 方法创建和调度。
  • 您的 api 方法目前仍在使用 cache 对象,而不是 cache-copy
  • cache 由 api 方法编辑,但随后被丢弃,因为新屏幕现在使用 cache-copy 对象。

第二种情况:

  • api方法接收cache
  • 该事件已从cache 中删除
  • navigation 方法接收更新的缓存并创建cache-copy
  • cache-copy 现在有更新的事件列表

需要注意的重要一点是cache-copy 对象的确切创建位置和时间。如果它是在事件被移除之前创建的,那么代码就可以正常工作。

比方说,当 api 方法删除事件时,您的导航方法会在准确的瞬间执行,即使不使用 async/await,您的代码也会按预期运行。

【讨论】:

  • 来自react-nativeAsyncStorage 是这样工作的吗?我从没想过它是有工作副本的东西。这样就可以解释了。对我来说,访问的总是一个地方(一个副本)。
  • 缓存理想地用于优化数据库的读取访问时间。根据您开发应用程序的平台,AsyncStorage 使用 SQLite 或文件存储来持久化数据。然而,缓存保存在内存中,因此直接从内存而不是磁盘存储中读取重要数据。
【解决方案2】:

async/await 正在按预期工作。在管理 Promise 时,您可以有两种选择:

//Using promises
const handleDone = () => {
  api.events.removeEventFromCache(eventId).then(() => {
    navigation.navigate(routes.Events);
  });//You can manage failure with .catch()
};

并使用async/await 就像您发布的那样,它会等到执行承诺,它本身并不会停止一切。此外,最好将其包装在 try/catch 块中,以防 Promise 失败。

Promise 对象表示异步操作的最终完成(或失败)及其结果值。

这意味着,当您调用 api.events.removeEventFromCache(eventId) 时,它不会立即完成,因此您必须使用两个选项之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-07
    • 2012-09-10
    • 2018-06-27
    • 2021-02-09
    • 2019-12-04
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    相关资源
    最近更新 更多