-2

I want to be able to make the console.log(key); make the log every 5 seconds, at the moment there is no delay and all the data gets logged at the same time.

//the location of my usres table
  var ref = new Firebase('https://myapp.firebaseIO.com/users/'); 

//ask fire base to get the records just once
    ref.once("value", function (snapshot) {

//loop through the retuned records
    snapshot.forEach(function (childSnapshot) {

// get just the value for the key
        var key = childSnapshot.key();

// log the key - this will be changed to send the value to another function
        console.log(key);

    });
})

The console.log above give me thousands of Id's, I need to pass these Id's to another function, If I pass all these id's all at one time the next function will blow up, so I want to pass them slowly, one by one to the next function. other ideas welcomed.

Bill
  • 4,614
  • 13
  • 77
  • 132
  • You'll need to use `setInterval()` -- see http://stackoverflow.com/questions/18070659/run-javascript-function-at-regular-time-interval – John Hascall Jan 08 '16 at 19:00
  • What is the real goal here? This looks highly artificial. See the [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378). Could probably save a lot of time by explaining what you're actually trying to achieve. – Kato Jan 08 '16 at 21:26
  • The for each is returning thousands of user id's, if I pass all the user id's to the next function at one time the script will blow up, so my thinking is to pass the id's to the next function every 5 seconds, which will give the next function plenty of time to complete. – Bill Jan 09 '16 at 01:02

4 Answers4

1

Use closure to get the value of key of current iteration after the setTimeout

Try this:

 var ref = new Firebase('https://myapp.firebaseIO.com/users/');
 ref.once("value", function(snapshot) {
   snapshot.forEach(function(childSnapshot, index) {
     var key = childSnapshot.key();
     setTimeout((function(key) {
       return function() {
         console.log(key);
       }
     })(key), 5000 * index);
   });
 });
Rayon
  • 36,219
  • 4
  • 49
  • 76
  • I tried but the log writes all the data to the console at the same time with no delay – Bill Jan 08 '16 at 19:17
0

Maybe you mean a custom array iterator that iterates to the next element in the array after a specified delay. I made one using functional programming principals to promote re usability. see below

/*
 * makeTimedForEach
 *
 * this will create an array itererator that will loop through an array
 * at a specified timeout delay.
 * 
 * @param {array}   arr    array to iterate
 *
 * @returns {Function} function to pass in callback and delay
 */
function makeTimedForEach(arr) {
  return function timedForEach(fn, delay) {
    var ii = 0;
    function iterate() {
      if (ii < arr.length) {
        // call the callback injecting the current element, index and array like native forEach
        fn.call( arr[ii], arr[ii], ii, arr );

        ii++;
        // call iterate again
        setTimeout(iterate, delay);
      }
    }
    // call for the first time you could add a setTimout here 
    // if you needed a delay at the start
    // setTimeout( iterate, delay );
    iterate();
  }
}

// Snapshot mock
function Snapshot(key) {
  this._key = key;
}
Snapshot.prototype = {
  key: function(){
    return this._key;
  }
}


var
  // a mock of the snapshot you get returned from `new FireBase`
  snapshot = [new Snapshot('one'), new Snapshot('two'), new Snapshot('three')],
  // create the iterator
  snapshotTimedForEach = makeTimedForEach(snapshot);

// call the iterator passing in the callback and the delay time
snapshotTimedForEach(function(childSnapshot, ii, arr) {
  console.log( childSnapshot.key(), childSnapshot, ii, arr );
}, 1000);
<script src="http://codepen.io/synthet1c/pen/WrQapG.js"></script>

original answer:

Im not sure if this is what you need, I cant see a point in logging the same result every 5 seconds. It seems you may want to poll the firebase api every 5 seconds

var ref = new Firebase('https://myapp.firebaseIO.com/users/');
ref.once("value", function(snapshot) {
  snapshot.forEach(function(childSnapshot) {

    var key = childSnapshot.key();

    // you can use setTimeout that recursively calls itself,
    // setTimeout will run the callback after the time has passed 
    // and wont lock up your thread like setInterval
    function log() {
      console.log(key);
      setTimeout( log, 5000);
    }
    // call log for the first time
    setTimeout( log, 5000);

  });
})
synthet1c
  • 6,152
  • 2
  • 24
  • 39
  • I tried but the log writes all the data to the console at the same time with no delay – Bill Jan 08 '16 at 19:23
  • thats weird. give me a sec, I'll use some dummy data. actually on second thought did you want to iterate over the forEach every 5 seconds are delay the console log for 5 seconds then continue each 5 seconds. – synthet1c Jan 08 '16 at 19:39
  • The for each is returning thousands of user id's, if I pass all the user id's to the next function the script will blow up, so my thinking is to pass the id's to the next function every 5 seconds, which will give the next function plenty of time to complete. – Bill Jan 09 '16 at 01:00
  • You really need to add more information into the question. That is relevant information that would have got you a better solution of chucking the array and processing in batches allowing other events to still fire so the thread is not completely blocked up until all records are processed. The script I provided will do something every 5 seconds and operate like a normal forEach so you could do what you want but it's not the best solution. just chuck the data pass that array to `makeTimedForEach` – synthet1c Jan 09 '16 at 01:26
0
var ref = new Firebase('https://myapp.firebaseIO.com/users/');

ref.once("value", function (snapshot) {

    for(var i=0; i<snapshot.lenght;i++){
        var childSnapshot = snapshot[i];

        var key = childSnapshot.key();

        setTimeout(function () {
            console.log(key);
        }, 5000); // will stop the loop for 5 seconds every time
    }


});
wmehanna
  • 394
  • 3
  • 15
  • I tried but the log writes all the data to the console at the same time with no delay – Bill Jan 08 '16 at 19:14
  • Instead of a .forEach function. try using a normal for loop; I cannot give you this an answer but as a suggestion since I had this similar issue in the past using forEach loop on the DOM, and using normal for loop fixed my issue. I cannot say why or how it happened since I did not searched further. – wmehanna Jan 08 '16 at 19:18
  • Im so set in my ways with the for each loop I cant even see how to change it for a for loop! Any pointers would be great – Bill Jan 08 '16 at 19:32
  • For some reason i get no errors and no console log? – Bill Jan 08 '16 at 19:50
  • my bad, i removed the extra {) closure I typed by error. If this doesn't work, i'll give it a shot tonight when I come back home. – wmehanna Jan 08 '16 at 19:52
  • Thank you for your kind help with this, the edit is still not creating an error or a log – Bill Jan 09 '16 at 01:16
  • 2
    A Firebase snapshot is not an array, so you cannot loop over its children like this. https://www.firebase.com/docs/web/api/datasnapshot/ `snapshot.forEach()` will loop over the children. – Frank van Puffelen Jan 09 '16 at 03:25
0

You can use setTimeout and recursive function like this:

function values(obj) {
    if (obj instanceof Array) {
        return obj.slice();
    } else {
        return Object.keys(obj).map(function(key) {
            return obj[key];
        });
    }
}

ref.once("value", function (snapshot) {
    var array = values(snapshot.val());
    (function process() {
       var item = array.shift();
       if (item) {
           var key = item.key();
           console.log(key);
           setTimeout(process, 5000);
       }
    })();
});
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • I tried the above and I get FIREBASE WARNING: Exception was thrown by user callback. TypeError: snapshot.slice is not a function – Bill Jan 08 '16 at 19:13
  • @Bill try `snapshot.val().slice()` – jcubic Jan 08 '16 at 19:57
  • FIREBASE WARNING: Exception was thrown by user callback. TypeError: snapshot.val(...).slice is not a function – Bill Jan 09 '16 at 01:08
  • @jcubic: Your approach sounds good. But `snapshot.val()` likely (given that OP is missing a JSON sample) returns an associative array of keys (Firebase uids or push ids) and values (the actual user data). In that case it is common to loop over the values with a `var val = snapshot.val(); Object.keys(val).forEach(function(key) { val[key]...` – Frank van Puffelen Jan 09 '16 at 03:22