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

Setting a timer for a long period of time, i.e. multiple minutes #97

Closed
saeedhei opened this issue Jul 14, 2017 · 58 comments
Closed

Setting a timer for a long period of time, i.e. multiple minutes #97

saeedhei opened this issue Jul 14, 2017 · 58 comments

Comments

@saeedhei
Copy link

I want to use firebase auth with react native for Login and Signup but I got a yellow error:
Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See (facebook/react-native#12981) for more info. (Saw setTimeout with duration 111862ms)

How Can I Fix That?
I don't want to ignore that, I want to understand this error and solve that with the best and Standard way.
And This is my Code:

 export default class Login extends Component {
        constructor(props) {
            super(props)
            this.state = {
                email: '',
                password: '',
                response: ''
            }
            this.signUp = this.signUp.bind(this)
            this.login = this.login.bind(this)
        }
        async signUp() {
            try {
                await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
                this.setState({
                    response: 'Account Created!'
                })
                setTimeout(() => {
                    this.props.navigator.push({
                        id: 'App'
                    })
                }, 1500)
            } catch (error) {
                this.setState({
                    response: error.toString()
                })
            }
        }
        async login() {
            try {
                await firebase.auth().createUserWithEmailAndPassword(this.state.email, this.state.password)
                this.setState({
                    response: 'user login in'
                })
                setTimeout(() => {
                    this.props.navigator.push({
                        id: 'App'
                    })
                })

            } catch (error) {
                this.setState({
                    response: error.toString()
                })
            }

        }
        render() {
            return (
                <View style={styles.container}>
                    <View style={styles.containerInputes}>
                        <TextInput
                            placeholderTextColor="gray"
                            placeholder="Email"
                            style={styles.inputText}
                          //  onChangeText={(email) => this.setState({ email })}
                            onChangeText={(email) => {console.log(email);}}
                        />
                        <TextInput
                            placeholderTextColor="gray"
                            placeholder="Password"
                            style={styles.inputText}
                            password={true}
                            onChangeText={(password) => this.setState({ password })}
                        />
                    </View>
                    <TouchableHighlight
                        onPress={this.login}
                        style={[styles.loginButton, styles.button]}
                    >
                        <Text
                            style={styles.textButton}
                        >Login</Text>
                    </TouchableHighlight>
                    <TouchableHighlight
                        onPress={this.signUp}
                        style={[styles.loginButton, styles.button]}
                    >
                        <Text
                            style={styles.textButton}
                        >Signup</Text>
                    </TouchableHighlight>
                </View>
            )
        }
    }

I Asked From Stackoverflow too, Link

@google-oss-bot
Copy link
Contributor

Hey there! I couldn't figure out what this issue is about, so I've labeled it for a human to triage. Hang tight.

@google-oss-bot
Copy link
Contributor

Hmmm this issue does not seem to follow the issue template. Make sure you provide all the required information.

@bojeil-google
Copy link
Contributor

I assume you are including real-time database in your code?
We pro-actively refresh the token when database or other Firebase services are included. The token typically has a lifetime of one hour. We would need to use some other native utility or external dependency to replace the underlying setTimeout usage for this. This will take some time to implement. It seems benign for now so I see this as a low priority.

@saeedhei
Copy link
Author

Yeah I'm using real-time database and when I added firebase to my project, I got This
svbzc
Thank you @bojeil-google

@justColbs
Copy link

@bojeil-google Could you please update here when this has been resolved? Thank you!

@andy-awsdev7
Copy link

andy-awsdev7 commented Aug 15, 2017

constructor() {
super();
console.ignoredYellowBox = [
'Setting a timer'
];
}

@liketurbo
Copy link

I wonder, this issue show up only in Android, and maybe it's caused by using react-navigator, I say this, because once I all repeat from tutorial and tutor doesn't get this error and only difference between our works it's I use react-navigator instead react-native-router-flux and I work with Android instead IOS

@liketurbo
Copy link

Maybe, we could throw this code below in to the project, and reset all setTimeout ?

const highestTimeoutId = setTimeout(() => ';');
for (let i = 0; i < highestTimeoutId; i++) {
    clearTimeout(i); 
}
// source: https://stackoverflow.com/questions/3847121/how-can-i-disable-all-settimeout-events

@saeedhei
Copy link
Author

When will This issue be resolved?

@bojeil-google
Copy link
Contributor

There are bunch of high priority features and bug fixes in the pipeline. We'll switch to this issue immediately after. It's been labeled as a P3 issue which is appropriate for its severity.

@mutazmq
Copy link

mutazmq commented Nov 25, 2017

Hello guys, any update on this issue please? I have not been able to use Firebase on Android because of it.

@mopx
Copy link

mopx commented Nov 25, 2017

Using the native sdk instead of the js/web sdk fixes the problem.

https://github.com/invertase/react-native-firebase

It involves a lot more configuration and it won’t work with Expo tho.

@bojeil-google
Copy link
Contributor

My understanding is that this is not a blocking issue and can be suppressed.
I will try to experiment with a quick solution using react-native-background-timer and report back.

@bojeil-google bojeil-google self-assigned this Nov 26, 2017
@bojeil-google
Copy link
Contributor

Ok, I tried testing this issue with react native 0.48.4 and firebase 4.6.2 using an Android emulator (API 25) and I was not able to replicate this. I am not getting the warning at all.

@Narutuffy
Copy link

I am still getting this warning

@bojeil-google
Copy link
Contributor

Can you provide more detailed information about your environment to facilitate replication?

@bogannathan
Copy link

bogannathan commented Nov 28, 2017 via email

@bojeil-google
Copy link
Contributor

I also used expo version ^21.0.0.

@clayrisser
Copy link

@brunolemos, I totally agree with you. But it definitely is nice to be able to hide the warnings while waiting for a proper fix.

@metavaults
Copy link

There is no fix yet? So many people have this problem!

@CodingBitsDev
Copy link

CodingBitsDev commented Mar 22, 2018

I have the exact same problem as @colinwong
I thought about switching to the realtime database, but the issue seems to be there as well.

As it is right now firebase and expo seem to be unusable together.

@pmdlt
Copy link

pmdlt commented Mar 25, 2018

@colinwong @LukasNavickas @Renji3 This problem is "normal" and has nothing to do with the timer error. Firestore is not supported by React Native (#283). The only solutions : Using Firebase Realtime Database or https://github.com/invertase/react-native-firebase (which is not compatible with Expo).

@jshcrowthe
Copy link
Contributor

Hey folks, figured I'd chime in here.

Ultimately the fix needs to be made on the react-native side as indicated in the message

See (facebook/react-native#12981)

There is a workaround for the warning that you are seeing that @bojeil-google mentioned that we could implement.

i.e.

I have found and successfully tested a workaround for this using multi-step short duration setTimeouts but this will only fix the issue from the auth side of things. Database also uses long duration setTimeouts too. So the firebase core should provide this common implementation.

Using multi-step short duration setTimeouts doesn't actually fix the problem though. The Timer module still stays active and the app is still subject to the performance issues indicated in the warning. The issue here is that, we have use cases that require long timers, and react-native doesn't optimize for that use case.

So the net of all that is: This bug can't be fixed here we can only work around the error there are workarounds available (see https://stackoverflow.com/questions/44603362/setting-a-timer-for-a-long-period-of-time-i-e-multiple-minutes) that disable the warning. Doing the work to disable the warning in our code, doesn't help the issue (beyond disabling the warning), and adds additional SDK code/weight that is completely unnecessary.

I'd recommend chiming in on the issue mentioned above (i.e. facebook/react-native#12981) if you aren't comfortable w/ the workaround provided.

@denimar
Copy link

denimar commented May 10, 2018

Maybe the best way to go through this problem is by changing JSTimers.js until they really fix it

@SKempin
Copy link

SKempin commented Jul 1, 2018

facebook/react-native#12981 (comment) has a cleaner temporary fix for this.

@usfslk
Copy link

usfslk commented Oct 1, 2018

We really need a solution for this.
I am getting the warning when using firebase authentication and realtime database

"expo": "^30.0.1",
"firebase": "^5.5.1",
"react": "16.3.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz",

@minhdang-idev
Copy link

Same problem here. I am using 30.0.1 and firebase 5.5.2.

@cristo-rabani
Copy link

cristo-rabani commented Oct 5, 2018

Work around issue with yellow warning 'Setting a timer' .

copy & import following file (as fast as you can ;-))

import {Platform, InteractionManager} from 'react-native';

const _setTimeout = global.setTimeout;
const _clearTimeout = global.clearTimeout;
const MAX_TIMER_DURATION_MS = 60 * 1000;
if (Platform.OS === 'android') {
// Work around issue `Setting a timer for long time`
// see: https://github.com/firebase/firebase-js-sdk/issues/97
    const timerFix = {};
    const runTask = (id, fn, ttl, args) => {
        const waitingTime = ttl - Date.now();
        if (waitingTime <= 1) {
            InteractionManager.runAfterInteractions(() => {
                if (!timerFix[id]) {
                    return;
                }
                delete timerFix[id];
                fn(...args);
            });
            return;
        }

        const afterTime = Math.min(waitingTime, MAX_TIMER_DURATION_MS);
        timerFix[id] = _setTimeout(() => runTask(id, fn, ttl, args), afterTime);
    };

    global.setTimeout = (fn, time, ...args) => {
        if (MAX_TIMER_DURATION_MS < time) {
            const ttl = Date.now() + time;
            const id = '_lt_' + Object.keys(timerFix).length;
            runTask(id, fn, ttl, args);
            return id;
        }
        return _setTimeout(fn, time, ...args);
    };

    global.clearTimeout = id => {
        if (typeof id === 'string' && id.startsWith('_lt_')) {
            _clearTimeout(timerFix[id]);
            delete timerFix[id];
            return;
        }
        _clearTimeout(id);
    };
}

@SMKH-PRO
Copy link

SMKH-PRO commented Dec 7, 2018

still getting this error :/ apps getting crashed due to this..!

@cristo-rabani
Copy link

Did you add 'fix code' before first setTimeout was used?

@MAfzalKhan1997
Copy link

MAfzalKhan1997 commented Dec 21, 2018

Did you add 'fix code' before first setTimeout was used?

Work around issue with yellow warning 'Setting a timer' .

copy & import following file (as fast as you can ;-))

import {Platform, InteractionManager} from 'react-native';

const _setTimeout = global.setTimeout;
const _clearTimeout = global.clearTimeout;
const MAX_TIMER_DURATION_MS = 60 * 1000;
if (Platform.OS === 'android') {
// Work around issue `Setting a timer for long time`
// see: https://github.com/firebase/firebase-js-sdk/issues/97
    const timerFix = {};
    const runTask = (id, fn, ttl, args) => {
        const waitingTime = ttl - Date.now();
        if (waitingTime <= 1) {
            InteractionManager.runAfterInteractions(() => {
                if (!timerFix[id]) {
                    return;
                }
                delete timerFix[id];
                fn(...args);
            });
            return;
        }

        const afterTime = Math.min(waitingTime, MAX_TIMER_DURATION_MS);
        timerFix[id] = _setTimeout(() => runTask(id, fn, ttl, args), afterTime);
    };

    global.setTimeout = (fn, time, ...args) => {
        if (MAX_TIMER_DURATION_MS < time) {
            const ttl = Date.now() + time;
            const id = '_lt_' + Object.keys(timerFix).length;
            runTask(id, fn, ttl, args);
            return id;
        }
        return _setTimeout(fn, time, ...args);
    };

    global.clearTimeout = id => {
        if (typeof id === 'string' && id.startWith('_lt_')) {
            _clearTimeout(timerFix[id]);
            delete timerFix[id];
            return;
        }
        _clearTimeout(id);
    };
}

This worked for me ... pretty solution !

@cpmech
Copy link

cpmech commented Jan 9, 2019

The problem persists, unfortunately...

@cpmech
Copy link

cpmech commented Jan 9, 2019

Work around issue with yellow warning 'Setting a timer' .

copy & import following file (as fast as you can ;-))

import {Platform, InteractionManager} from 'react-native';

const _setTimeout = global.setTimeout;
const _clearTimeout = global.clearTimeout;
const MAX_TIMER_DURATION_MS = 60 * 1000;
if (Platform.OS === 'android') {
// Work around issue `Setting a timer for long time`
// see: https://github.com/firebase/firebase-js-sdk/issues/97
    const timerFix = {};
    const runTask = (id, fn, ttl, args) => {
        const waitingTime = ttl - Date.now();
        if (waitingTime <= 1) {
            InteractionManager.runAfterInteractions(() => {
                if (!timerFix[id]) {
                    return;
                }
                delete timerFix[id];
                fn(...args);
            });
            return;
        }

        const afterTime = Math.min(waitingTime, MAX_TIMER_DURATION_MS);
        timerFix[id] = _setTimeout(() => runTask(id, fn, ttl, args), afterTime);
    };

    global.setTimeout = (fn, time, ...args) => {
        if (MAX_TIMER_DURATION_MS < time) {
            const ttl = Date.now() + time;
            const id = '_lt_' + Object.keys(timerFix).length;
            runTask(id, fn, ttl, args);
            return id;
        }
        return _setTimeout(fn, time, ...args);
    };

    global.clearTimeout = id => {
        if (typeof id === 'string' && id.startWith('_lt_')) {
            _clearTimeout(timerFix[id]);
            delete timerFix[id];
            return;
        }
        _clearTimeout(id);
    };
}

it seems to work but I had to replace startWith by startsWith

thanks

@malikimran34
Copy link

an old issue in firebase still waiting for a proper fix

screenshot_1548759939

@moGeekHex
Copy link

this warning from socket firebase add that code to the App file to get rid of that warning
console.ignoredYellowBox = [
'Setting a timer'
];

@rauldeheer
Copy link

Is this getting fixed any time soon? I have the same issue and I see it has been here since 2017. I'm using Expo SDK v32 and I'm not using the realtime database but rather the Firebase Firestore.

@carlosenambam
Copy link

My friends I had the same error just 20 minutes ago and I figured out the cause of the error, I had to define a value for the iterations param in the Animated.loop function:

const animation = Animated.loop( Animated.timing(animatedRotation, { toValue: 1, duration: 800, easing: Easing.linear, useNativeDriver: true }), { iterations: 20 // Just add a reasonable value here } );

By default the value of the "iterations" param is -1, meaning the animation will run with infinite loops, but this feature is implemented by using a setTimeOut function with a big number of seconds in order to run the animation 'infinite' times.

Problem Solved

@HOllarves
Copy link

My friends I had the same error just 20 minutes ago and I figured out the cause of the error, I had to define a value for the iterations param in the Animated.loop function:

const animation = Animated.loop( Animated.timing(animatedRotation, { toValue: 1, duration: 800, easing: Easing.linear, useNativeDriver: true }), { iterations: 20 // Just add a reasonable value here } );

By default the value of the "iterations" param is -1, meaning the animation will run with infinite loops, but this feature is implemented by using a setTimeOut function with a big number of seconds in order to run the animation 'infinite' times.

Problem Solved

Could yo explain a bit more about your solution? I actually never declare an animation variable in my app.

Let's just hope a proper bug fix comes.
Thanks!

@mikecappie
Copy link

Has anyone managed to find a fix for this yet? It doesn't prevent development or stop the app working but it's a bit of a pain and I don't like the idea of just supressing an underlying issue, I will for now though.

@SohamToraskar
Copy link

SohamToraskar commented Apr 22, 2019

To sort this out you need to hard code the value, increase the value of the variable MAX_TIMER_DURATION_MS. Here are the steps:

Go to node_modules/react-native/Libraries/Core/Timer/JSTimers.js

Look for the variable MAX_TIMER_DURATION_MS

Change 60 * 1000 to 10000 * 1000

Save the changes and re-build your app.

This worked for me.
https://stackoverflow.com/a/46678121

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

No branches or pull requests