Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncStorage not fulfilling promise on Android 7+ #14101

Closed
jsdario opened this issue May 22, 2017 · 123 comments
Closed

AsyncStorage not fulfilling promise on Android 7+ #14101

jsdario opened this issue May 22, 2017 · 123 comments
Labels
Platform: Android Android applications. Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.

Comments

@jsdario
Copy link
Contributor

jsdario commented May 22, 2017

Issue

I am using redux-persist in a react native project, that runs just fine in a broad number of devices execept Android 7. I am trying to debug the problem on why my AsyncStorage is nor persisting and found this:

The following code executes inside React Native component lifecycle's

  componentDidMount() {
    attachObservables(store)
    setInterval(async () => {
      console.log('Inside setInterval')
      const data = await AsyncStorage.getAllKeys()
      console.log('inside the getAllKeys')
      data.forEach(async k => {
        const value = await AsyncStorage.getItem(k)
        console.group(k)
        console.log(value)
        console.groupEnd()
      })
    }, 3000)
  }

Code after 'Inside setInterval' is never called. It only runs once if outside the setInterval. If I call once the code outside the setInterval it appears to run just fine. I also tried callback format vs async / await version but it does not seem to matter.

Same problem I had using firebase js library (callbacks never return after the first one). I am now looking for alternatives to workaround the problem.

Works with setImmediate and InteractionManager.runAfterInteractions. Seems that redux-persist uses setImmediate or fallsback to setTimeout.

Any ideas?

Additional Information

  • React Native version: React Native 0.40+ (last tested on RN@0.44)
  • Platform: Only Android 7 and above
  • Development Operating System: Mac os, Node 7.4
  • Dev tools:
android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"

    defaultConfig {
        multiDexEnabled true
        applicationId "com.netbeast.yeti"
        minSdkVersion 16
        targetSdkVersion 24
        versionCode 69
        versionName "1.3.91"
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
    }

In case this is a user level question I opened a question on stackoverflow, no luck yet, https://stackoverflow.com/questions/44114061/asyncstorage-is-not-returning-the-callback?noredirect=1#comment75248695_44114061

@dinzo
Copy link

dinzo commented Jun 30, 2017

@jsdario any updates on this? were you able to work around or resolve the problem?

@jsdario
Copy link
Contributor Author

jsdario commented Jun 30, 2017

I was not able to fix it, but I cooked a heavy and chunky workaround. I simply reimplemented the AsyncStarage API around https://github.com/itinance/react-native-fs so we could use it as storage in redux-persist.

Here it is the package https://github.com/netbeast/redux-persist-react-native-fs @dinzo

If I learn any more I'll share it. I have to say that we are using a set of advanced Android build tools, which might be the reason. The problem still exists on react-native 0.44 and 0.45.

@hramos hramos added the Icebox label Sep 21, 2017
@esamattis
Copy link

I'm seeing this too. The promise returned by AsyncStorage.getItem() just never resolves on Android. iOS is fine. I'm on RN 0.50RC.

@yinghang
Copy link

Can confirm that I'm seeing this too. After doing a few bundle reloads, I start getting the Maximum call stack size exceeded error.

@RickDT

This comment has been minimized.

@RickDT
Copy link

RickDT commented Nov 20, 2017

After further investigation: in my case I had an AsyncTask in some Java code (a local web server in my case) that was blocking and hence blocking other AsyncTasks (which AsyncStorage relies on). Setting my AsyncTask to execute in parallel to other tasks (via myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) instead of myTask.execute()) fixed the issue.

@yinghang

This comment has been minimized.

@allmaxgit

This comment has been minimized.

@HumanUndead

This comment has been minimized.

@jsdario
Copy link
Contributor Author

jsdario commented Nov 21, 2017

I submitted a Pull Request with the proposed solution by @RickDT, so far it is working for me.

@dabit3
Copy link
Contributor

dabit3 commented Nov 21, 2017

Thanks @jsdario .

One hack that may work is something like this:

const resolvedPromisesArray = [
        AsyncStorage.getItem(TOKEN_KEY),
        AsyncStorage.getItem(TOKEN_KEY),
        AsyncStorage.getItem(TOKEN_KEY),
        AsyncStorage.getItem(TOKEN_KEY),
        AsyncStorage.getItem(TOKEN_KEY)
];
this.token = await Promise.race(resolvedPromisesArray);

Because it only seems to be happening sporadically, hitting it multiple times may give you a better chance of one of them resolving.

I know, this is very ugly 🥇

@allmaxgit
Copy link

allmaxgit commented Nov 24, 2017

@jsdario waiting to merge your PR :) Thanks 👍
Update: But this does not completely solve the problem :(

@jsdario
Copy link
Contributor Author

jsdario commented Dec 12, 2017

How not? I am using it in production, can you further describe the issue @allmaxgit ?

@RoBYCoNTe
Copy link

I'm having this problem too. First time I execute the app code, AsyncStorage works fine, after few calls (4-5), getItem never call promise resolve function.

@UberMC
Copy link

UberMC commented Dec 13, 2017

Might work once after freshly rebooting device. I have to find an alternative AsyncStorage doesn't work for me, which sucks because saving things on device is so important.

?FIXED
Updating to 0.51 appeared to fix this I was on 0.5.03

But
After reload android emulator with 'rr' it appears to break and I have to do react-native run-android again.

@logovaser

This comment has been minimized.

@manjeets12

This comment has been minimized.

@julestruong

This comment has been minimized.

@logovaser
Copy link

logovaser commented Dec 18, 2017

@julestruong I face this issue on Ubuntu on ejected project. Expo project is fine, projects on Windows also doesn't have any issues.
Seems like something is blocking the debugger port for AsyncStorage, hard to say exactly.
Hope this will help you.

@Fortidude
Copy link

Faced the same issue on emulator android 7 and device with android 7.
RN 0.50

hm... @RickDT where should I inject you code with myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)

I dont make any other async task hm...

@RickDT
Copy link

RickDT commented Dec 20, 2017

@Fortidude it will probably be in a 3rd party dependency, like an npm module that uses native Java code. Or Java code that you've introduced into the project.

@tuomashatakka
Copy link

One way to solve this for now is to have a completely separate interface for the development environment's storage where the async storage fails to function.

That's what I did – I got tired of figuring on solving the problem so I wrote a simple wrapper for the storage. The storage uses idb when the app is run in the development mode and the AsyncStorage if the remote debugger is disabled or running in production mode.

Feel free to use the wrapper I wrote (available on https://gitlab.com/snippets/1690090). I haven't had a single problem with the storage ever since I enabled this on my most recent RN project.

The only downside is that Reactotron fails to show the storage contents automatically since AsyncStorage isn't used.

@Graren
Copy link

Graren commented Dec 31, 2017

How is progress on this issue? I'm seeing the same error on removing multiple keys and waiting with promise.all, it just never resolves

@MedinaGitHub

This comment has been minimized.

@gadfil
Copy link

gadfil commented Apr 16, 2018

@aMarCruz you are right
Add rejection in the setItem and clear methods
I hope so too AsyncStorage in react-native will be fix in the near future
And that's why I use interface AsyncStorage
As soon as AsyncStorage will be fixed I'll back to use AsyncStorage

@xiaoyu311

This comment has been minimized.

@jonczeck
Copy link

jonczeck commented Apr 16, 2018

@xiaoyu311 You are 100% wrong. AsyncStorage uses an SQLite DB under the hood which doesn't require any permission.

@apcjs
Copy link

apcjs commented Apr 18, 2018

I went back to a 6.0 emulator and still found the same issue. So this is not just a 7+ problem

@DylanVann

This comment has been minimized.

gornostal added a commit to gornostal/react-native-demo-dapp that referenced this issue Apr 18, 2018
@asmarcz

This comment has been minimized.

@pkhien95

This comment has been minimized.

@jshearer
Copy link

Is this actually genuinely broken in RN core, and has been since May 2017, and the only solution is to use a third party library that replaces it?

@ohtangza
Copy link

@jsdevel I would say yes. It might take a long time to recover the credibility of this API again for the existing developers, I guess.

@GuySerfaty

This comment has been minimized.

@venil7
Copy link

venil7 commented May 6, 2018

I'm seeing this issue on RN 0.55.3

@ohtangza

This comment has been minimized.

@hramos hramos added the Help Wanted :octocat: Issues ideal for external contributors. label May 7, 2018
@kennethnym

This comment has been minimized.

@Rpaixao

This comment has been minimized.

@kennethnym

This comment has been minimized.

@facebook facebook locked as too heated and limited conversation to collaborators May 23, 2018
@kelset
Copy link
Contributor

kelset commented May 23, 2018

Since this issue is just polluted by useless comments, no need to keep it unlocked.

If you are looking for solutions, there are snippets proposed in the past comments, and two open PRs that are being discussed:

#16905

#18522

@hramos hramos added the Resolution: PR Submitted A pull request with a fix has been provided. label May 29, 2018
@hramos
Copy link
Contributor

hramos commented Jun 27, 2018

For those following along, #18522 has been approved and we're working on getting it merged.

hramos pushed a commit to hramos/react-native that referenced this issue Jun 28, 2018
Summary:
This patch is a bit of a hack job, but I'd argue it's necessary to dramatically improve the dev UX on Android devices. Somewhere in react-native, there's a shared SerialExecutor which AsyncStorage uses that is getting blocked, causing remote debugging to occasionally hang indefinitely for folks making AsyncStorage requests. This is frustrating from a dev UX perspective, and has persisted across several versions as far back as RN 0.44, and still remains on RN 0.54.

The issue seems to only happen on Android > 7+, which is likely because the ThreadPoolExecutor behavior changed in this version:
https://stackoverflow.com/questions/9654148/android-asynctask-threads-limits

Fixes facebook#14101

We've been using this patch in production for the past 4 months on our team by overriding the AsyncStorage native module. We use AsyncStorage extensively for offline data and caching.

You can test by compiling this commit version into a test react native repository that is set to build from source:

```sh
git clone https://github.com/dannycochran/react-native rnAsyncStorage
cd rnAsyncStorage
git checkout asyncStorage
cd ..
git clone https://github.com/dannycochran/asyncStorageTest
yarn install
cp -r ../rnAsyncStorage node_modules/react-native
react-native run-android
```

No documentation change is required.

facebook#16905

[Android] [BUGFIX] [AsyncStorage] - Fix AsyncStorage causing remote debugger to hang indefinitely.
Closes facebook#18522

Differential Revision: D8624088

fbshipit-source-id: 2a599fbca270a4826063cd93be8eaf796f34f57a
@kelset kelset removed Resolution: PR Submitted A pull request with a fix has been provided. Help Wanted :octocat: Issues ideal for external contributors. labels Jul 30, 2018
darabi pushed a commit to darabi/react-native that referenced this issue Aug 9, 2018
Summary:
This patch is a bit of a hack job, but I'd argue it's necessary to dramatically improve the dev UX on Android devices. Somewhere in react-native, there's a shared SerialExecutor which AsyncStorage uses that is getting blocked, causing remote debugging to occasionally hang indefinitely for folks making AsyncStorage requests. This is frustrating from a dev UX perspective, and has persisted across several versions as far back as RN 0.44, and still remains on RN 0.54.

The issue seems to only happen on Android > 7+, which is likely because the ThreadPoolExecutor behavior changed in this version:
https://stackoverflow.com/questions/9654148/android-asynctask-threads-limits

Fixes facebook#14101

We've been using this patch in production for the past 4 months on our team by overriding the AsyncStorage native module. We use AsyncStorage extensively for offline data and caching.

You can test by compiling this commit version into a test react native repository that is set to build from source:

```sh
git clone https://github.com/dannycochran/react-native rnAsyncStorage
cd rnAsyncStorage
git checkout asyncStorage
cd ..
git clone https://github.com/dannycochran/asyncStorageTest
yarn install
cp -r ../rnAsyncStorage node_modules/react-native
react-native run-android
```

No documentation change is required.

facebook#16905

[Android] [BUGFIX] [AsyncStorage] - Fix AsyncStorage causing remote debugger to hang indefinitely.
Pull Request resolved: facebook#18522

Differential Revision: D8624088

Pulled By: hramos

fbshipit-source-id: a1d2e3458d98467845cb34ac73f2aafaaa15ace2
darabi pushed a commit to darabi/react-native that referenced this issue Aug 10, 2018
Summary:
This patch is a bit of a hack job, but I'd argue it's necessary to dramatically improve the dev UX on Android devices. Somewhere in react-native, there's a shared SerialExecutor which AsyncStorage uses that is getting blocked, causing remote debugging to occasionally hang indefinitely for folks making AsyncStorage requests. This is frustrating from a dev UX perspective, and has persisted across several versions as far back as RN 0.44, and still remains on RN 0.54.

The issue seems to only happen on Android > 7+, which is likely because the ThreadPoolExecutor behavior changed in this version:
https://stackoverflow.com/questions/9654148/android-asynctask-threads-limits

Fixes facebook#14101

We've been using this patch in production for the past 4 months on our team by overriding the AsyncStorage native module. We use AsyncStorage extensively for offline data and caching.

You can test by compiling this commit version into a test react native repository that is set to build from source:

```sh
git clone https://github.com/dannycochran/react-native rnAsyncStorage
cd rnAsyncStorage
git checkout asyncStorage
cd ..
git clone https://github.com/dannycochran/asyncStorageTest
yarn install
cp -r ../rnAsyncStorage node_modules/react-native
react-native run-android
```

No documentation change is required.

facebook#16905

[Android] [BUGFIX] [AsyncStorage] - Fix AsyncStorage causing remote debugger to hang indefinitely.
Pull Request resolved: facebook#18522

Differential Revision: D8624088

Pulled By: hramos

fbshipit-source-id: a1d2e3458d98467845cb34ac73f2aafaaa15ace2
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Dec 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Platform: Android Android applications. Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests