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

Support for asynchronous iterators (async for of) #551

Closed
raffaeler opened this issue Apr 27, 2020 · 11 comments
Closed

Support for asynchronous iterators (async for of) #551

raffaeler opened this issue Apr 27, 2020 · 11 comments

Comments

@raffaeler
Copy link

Asynchronous iterators and generators (aka await for ... of) are available as part of ES2018.
How can I use it in a react-native app? Currently there is no metro support for them.

Example:

// generator
 async function* gen() {
     yield 'a';
     yield 'b';
     return 2;
 }

// consumer
try {
    for await (const t of gen()) {
        console.log(t)
    }
}
catch(err) {
    console.log("err", err);
}

Any suggestion to workaround the issue is welcome. I could not find anything for using them.

Thanks

@luisnunes111
Copy link

+1

@ls-andrew-goodale
Copy link

JavaScriptCore in iOS 12+ supports them natively, as does JavaScriptCore bundled for Android. Can you set your minimum required iOS to 12?

@berdyshev
Copy link

any updates on this? I have also issues with getting this to work with the following error:

TypeError: Invalid attempt to iterate non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.

@newyankeecodeshop
Copy link
Contributor

newyankeecodeshop commented Jul 26, 2021

@berdyshev I was able to figure out what was going wrong. That error is due to an error in the @babel/plugin-transform-for-of plugin. It (mistakenly) tries to convert for await of statements with the same code as for of, and uses the wrong iterator property accessor.

I was able to workaround the problem by adding @babel/plugin-proposal-async-generator-functions to my babel.config.js.

@JSonicV
Copy link

JSonicV commented Sep 24, 2021

JavaScriptCore in iOS 12+ supports them natively, as does JavaScriptCore bundled for Android. Can you set your minimum required iOS to 12?

@ls-andrew-goodale, do you know the minimum requirements for Android?
This is my babel.config.js

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
        "@babel/plugin-proposal-async-generator-functions",
        "react-native-reanimated/plugin"
  ],
};

but for android I receive this message:
TypeError: Object is not async iterable

my build.gradle, if needed, is:

buildscript {
  ext {
        buildToolsVersion = "30.0.2"
        minSdkVersion = 21
        compileSdkVersion = 30
        targetSdkVersion = 30
        ndkVersion = "20.1.5948944"
        androidXCore = "1.6.0"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:4.2.1")
        classpath "com.google.gms:google-services:4.3.10"
    }
}
allprojects {
    repositories {
        mavenCentral()
        mavenLocal()
        maven {
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            url("$rootDir/../node_modules/jsc-android/dist")
        }
        google()
        maven { url "https://www.jitpack.io" }
    }
}

in app/build.gradle I have:

def jscFlavor = 'org.webkit:android-jsc:+'

Thanks in advance

@ls-andrew-goodale
Copy link

@JSonicV I use a very similar Babel config and don't have that error. Unfortunately, even though the Android JavaScriptCore supports async iteration, we have to use the Babel config to workaround the bug in @babel/plugin-transform-for-of which tries to process for async () loops as synchronous iterator loops.

Is your type error coming from using a Generator or a custom Iterable?

@JSonicV
Copy link

JSonicV commented Sep 29, 2021

@ls-andrew-goodale It is from Generators, which are massively used in SocketCluster to listen and consume events.
Mixing all the solutions here proposed, I solved the problem for IOS. For Android, instead, it persits and I can't figure out why..
I add package.json, hoping it could be useful

{
  "name": "myapp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
  },
  "dependencies": {
    "@react-native-community/async-storage": "^1.12.1",
    "@react-native-community/masked-view": "^0.1.11",
    "@react-native-community/netinfo": "6.0.2",
    "@react-native-firebase/app": "^12.8.0",
    "@react-native-firebase/messaging": "^12.8.0",
    "@react-navigation/native": "^6.0.4",
    "@types/socketcluster-client": "^15.1.5",
    "axios": "^0.21.0",
    "expo": "^42.0.0",
    "expo-splash-screen": "^0.11.4",
    "expo-sqlite": "~9.2.1",
    "expo-status-bar": "^1.0.0",
    "expo-updates": "^0.8.5",
    "lodash": "^4.17.15",
    "moment": "^2.27.0",
    "moment-timezone": "^0.5.31",
    "native-base": "^3.2.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-native": "0.65.1",
    "react-native-fix-image": "^2.1.0",
    "react-native-gesture-handler": "~1.10.3",
    "react-native-google-signin": "^2.1.1",
    "react-native-modal": "^13.0.0",
    "react-native-reanimated": "2.3.0-alpha.3",
    "react-native-rename": "^2.5.0",
    "react-native-safe-area-context": "~3.3.2",
    "react-native-screens": "~3.7.2",
    "react-native-simple-toast": "^1.1.2",
    "react-native-unimodules": "~0.14.8",
    "react-native-web": "~0.17.1",
    "react-navigation": "^4.4.4",
    "react-navigation-drawer": "^2.7.0",
    "react-navigation-header-buttons": "^9.0.0",
    "react-navigation-stack": "^2.10.0",
    "react-navigation-tabs": "^2.11.0",
    "react-redux": "^7.2.0",
    "redux": "^4.0.5",
    "redux-thunk": "^2.3.0",
    "socketcluster-client": "^16.0.2"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/plugin-proposal-async-generator-functions": "^7.15.4",
    "@babel/runtime": "^7.12.5",
    "@react-native-community/eslint-config": "^3.0.1",
    "@types/jest": "^27.0.2",
    "@types/react-native": "^0.65.0",
    "@types/react-test-renderer": "^17.0.1",
    "babel-jest": "^27.2.1",
    "eslint": "^7.14.0",
    "jest": "^27.2.1",
    "metro-react-native-babel-preset": "^0.66.0",
    "react-native-codegen": "^0.0.8",
    "react-test-renderer": "17.0.2",
    "typescript": "^4.4.3"
  },
  "resolutions": {
    "@types/react": "^17"
  },
  "jest": {
    "preset": "react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ]
  }
}

nevilm-lt pushed a commit to nevilm-lt/metro that referenced this issue Mar 14, 2022
Summary:
**Summary**

Async Generators and `for await` are part of ES2018. This PR adds `plugin-proposal-async-generator-functions` to the react native preset.
See https://babeljs.io/docs/en/babel-plugin-proposal-async-generator-functions

Fixes facebook#551

**Test plan**

I added a test `transforms async generators` to `index-test.js`.

Pull Request resolved: facebook#747

Reviewed By: motiz88

Differential Revision: D33621536

Pulled By: rh389

fbshipit-source-id: 0e07e6132e894fb5ad455627c2a33674f904a2fc
nevilm-lt pushed a commit to nevilm-lt/metro that referenced this issue Apr 21, 2022
Summary:
**Summary**

Async Generators and `for await` are part of ES2018. This PR adds `plugin-proposal-async-generator-functions` to the react native preset.
See https://babeljs.io/docs/en/babel-plugin-proposal-async-generator-functions

Fixes facebook#551

**Test plan**

I added a test `transforms async generators` to `index-test.js`.

Pull Request resolved: facebook#747

Reviewed By: motiz88

Differential Revision: D33621536

Pulled By: rh389

fbshipit-source-id: 0e07e6132e894fb5ad455627c2a33674f904a2fc
nevilm-lt pushed a commit to nevilm-lt/metro that referenced this issue Apr 22, 2022
Summary:
**Summary**

Async Generators and `for await` are part of ES2018. This PR adds `plugin-proposal-async-generator-functions` to the react native preset.
See https://babeljs.io/docs/en/babel-plugin-proposal-async-generator-functions

Fixes facebook#551

**Test plan**

I added a test `transforms async generators` to `index-test.js`.

Pull Request resolved: facebook#747

Reviewed By: motiz88

Differential Revision: D33621536

Pulled By: rh389

fbshipit-source-id: 0e07e6132e894fb5ad455627c2a33674f904a2fc
@sohan-dutta
Copy link

sohan-dutta commented May 4, 2023

@JSonicV I use a very similar Babel config and don't have that error. Unfortunately, even though the Android JavaScriptCore supports async iteration, we have to use the Babel config to workaround the bug in @babel/plugin-transform-for-of which tries to process for async () loops as synchronous iterator loops.

Is your type error coming from using a Generator or a custom Iterable?

Hi @JSonicV have you found any solution to this? I'm also facing this issue when implementing Socket Cluster in React Native in Android

@robhogan
Copy link
Contributor

robhogan commented May 4, 2023

Hi @sohan-dutta, would you be able to open a new issue describing the behaviour you’re seeing with your Babel and Metro config? I don’t think this bug is on our radar at the moment.

@haakonnessjoen
Copy link

haakonnessjoen commented May 25, 2023

I have the same problem trying to implement Socket Cluster in react native on ios/android. Did anyone figure this out? The babel config didn't help at all.

EDIT: I seem to have solved it.

first do the following:

yarn add react-native-get-random-values
npx pod-install
yarn add -D core-js

react-native-get-random-values is needed by the ws version that socket cluster uses, so not related to this specific issue, but should be interesting for @sohan-dutta . core-js is needed by the babel-workaround we are going to do.

After installing those dependencies, you need to add this to the top of your App.tsx (before everything else):

import 'react-native-get-random-values';
import "core-js/modules/es.symbol.async-iterator";

Again, the react-native-get-random-values module is for a separate issue regarding socket cluster's ws. But for the for await issue. If i understood correctly, babel has an issue where it parses the for await loop in the wrong order, so it converts for ( of ) loops before it checks for the for await ( of ) code. But by loading the core-js/modules/es.symbol.async-iterator it loads the for await ( of ) parser first. I might be totally off road here. But at least for me it fixed everything.

@sohan-dutta
Copy link

I was able to solve using this polyfill @azure/core-asynciterator-polyfill

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants