4

I have found behaviour that makes me trouble in JavaScript. I have two functions:

var show_uploaded = function( data_photo ) that gets informations about uploaded photos as a parameter,

function exif_like(path){/*working with my image*/ console.log('exif_like END'); }
that gets path to every single one uploaded photo as a parameter.

I made code like this:

var show_uploaded = function( data_photo ){
    for( var z = 0; z < data_photo.length; z++ ){ 
       var send_image_name = uploaded_photo[z].name;
       $.ajax({
            data: { compare : send_image_name },
            url: 'get_panorama.php',
            method: 'POST', // or GET
            success: function( path ){
                exif_like( path );
                console.log('FOR LOOP END');
            }
       });
    }
};

But what I see in console is that "FOR LOOP END" log is displayed before "exif_like END" log. And this causes some unpredictable behaviour in my code.

Is there any solution how to continue for loop after exif_like() function is done?

7
  • Well, you're going to get multiple logs of "for loop end", as that's inside the for loop. Are you sure you're not seeing one of those before a different "exif end" - they should still be appearing in pairs? Commented Mar 4, 2016 at 16:36
  • Can we see more of the contents of exif_like? Are you using async methods inside of it? Commented Mar 4, 2016 at 16:43
  • For example when i upload 3 photos, konsole prints out: "FOR LOOP END", "FOR LOOP END", "FOR LOOP END", "exif_like END", "exif_like END", "exif_like END".. and they should still be appearing in pairs like this: "exif_like END", "FOR LOOP END", "exif_like END", "FOR LOOP END", "exif_like END", "FOR LOOP END" Commented Mar 4, 2016 at 16:44
  • With the code you've posted, you should be seeing what you're expecting. exif_like must also be doing something asynchronously with the logging inside that, rather than directly in the function as per your question. Commented Mar 4, 2016 at 16:52
  • @JamesThorpe Yes, it does something asynchronously but it is inside exif_like() and I dont see it as a reason to return from this function and continue loop before the last line of exif_like() is executed. Am I missing something? Commented Mar 4, 2016 at 16:58

3 Answers 3

2

If the remainder of processes return expected results, and exif_like actually only performs console.log() you could try using $.when()

$.when(exif_like( path )).then(function() {console.log("FOR LOOP END")})
Sign up to request clarification or add additional context in comments.

6 Comments

And if my function returns true in the end, after mentioned console.log(), is it possible to do somethink like this: $.when(exif_like( path ) == true).then(function() {console.log("FOR LOOP END")}) ?
@PetrBečka Yes, it should be possible to do something like that. though, is this your Question as described at OP and comment stackoverflow.com/questions/35801224/… ? Also note, no value appears to be returned from exif_like( path ) at js at Question ?
Thank you I'll try. Yes, this is my question.
Would exif_like(path) return true only once ?
missunderstood maybe. yes, only once, in the end of the function
|
1

If you are trying to have exif_like() do things in between Ajax calls, just have your exif_like() function call the next Ajax request when it finishes.

Using test data from json placeholder, something like this would work:

JavaScript

uploaded_photo = [{name: 1},{name: 2},{name: 6},{name: 8},{name: 9},{name: 11},{name: -1}]
pointer = 0;

function exif_like(path){
    /*working with my image*/ 
  obj = JSON.parse(path)
  if(obj.length > 0) {
    console.log('\t\tdata returned:'+obj[0].id + ' '+obj[0].title)
        console.log('exif_like END for '+obj[0].id);
  } else {
    console.log('\t\tNo data returned')
        console.log('exif_like END');  
  }

  /* Code here can be executed before the next Ajax call */
  console.log('Do stuff before the next ajax call...')

  pointer++;
  if(pointer < uploaded_photo.length) {
    show_uploaded();
  }
}

var show_uploaded = function(){
    console.log('---Start of Ajax call---');

  $.ajax({
    data: { id : uploaded_photo[pointer].name },
    url: 'https://jsonplaceholder.typicode.com/posts',
    method: 'GET', 
    complete: function( xhr ){
        console.log('---End of Ajax call---');
      exif_like( xhr.responseText );
    }
  });
};

show_uploaded()

Output

---Start of Ajax call---
---End of Ajax call---
data returned:1 sunt aut facere repellat provident occaecati excepturi optio reprehenderit
exif_like END for 1
Do stuff before the next ajax call...
---Start of Ajax call---
---End of Ajax call---
data returned:2 qui est esse
exif_like END for 2
Do stuff before the next ajax call...
---Start of Ajax call---
---End of Ajax call---
data returned:6 dolorem eum magni eos aperiam quia
exif_like END for 6
Do stuff before the next ajax call...
---Start of Ajax call---
---End of Ajax call---
data returned:8 dolorem dolore est ipsam
exif_like END for 8
Do stuff before the next ajax call...
---Start of Ajax call---
---End of Ajax call---
data returned:9 nesciunt iure omnis dolorem tempora et accusantium
exif_like END for 9
Do stuff before the next ajax call...
---Start of Ajax call---
---End of Ajax call---
data returned:11 et ea vero quia laudantium autem
exif_like END for 11
Do stuff before the next ajax call...
---Start of Ajax call---
---End of Ajax call---
No data returned
exif_like END

JS Fiddle Example: https://jsfiddle.net/igor_9000/wwj11udx/3/

Hope that helps!

*Edit: Updated code to use the complete function instead, in the event there are requests that don't succeed.

Comments

1

Replace for loop to while loop, condition is until data_photo not empty, prior starting while loop create flag variable which would be boolean identifier that ajax success handler finished and next ajax can be sent. See code below with commented changes :

var show_uploaded = function( data_photo ){
  // Create flag 
  var flag = true;
  var length = data_photo;

  // continue loop execution until data_photo not empty
  while (length){
    if(flag){
        var send_image_name = uploaded_photo[--length].name;
        // Set flag to false, until success executed
        flag = false;
        $.ajax({
            data: { compare : send_image_name },
            url: 'get_panorama.php',
            method: 'POST', // or GET
            success: function( path ){
                exif_like( path );
                console.log('FOR LOOP END');
                // We are ready to perform next ajax, set flag to true.
                flag = true;
            },
            error: function( path ){
                // Error or not we have to set flag to true to allow further iterating
                flag = true;
            }
       });
   }
}
};

6 Comments

@HurricaneHamilton I've added comments to code and link with description of while loop in js
Thanks for updating the code. It looks like this will start the while loop, send the first ajax request, then skip the rest of the items, because there is no way that me.flag gets set to true before the while loop finishes. Remember that the success and error callbacks are async.
Yes, you are right, also new ajax won't be sent and data_photo won't be popped for 1 item until flag became true which means previous ajax shall be in onSuccess or on onError phase.
It looks very nice but I'm kind of lost from your comments guys, do think this is gonna work in the end?
@PetrBečka yes it suppose to work, important moment is to keep track value of me.flag to be true when would be ajax finished, because otherwise you can be in trouble with infinitive while loop
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.