0

I am trying to make a google shortener analytic tools by javascript, it's my code:

 <script>

  function makeRequest() {
    for (var i=0; i < shortUrl.length; i++){
      var url = shortUrl[i];
      var request = gapi.client.urlshortener.url.get({
        'shortUrl': url,
        'projection':'FULL',
      });
      request.execute(function(response) {
        console.log(response); //here is the problem begin
        var result = {
          short: response.id,
          clicks: response.analytics.allTime.shortUrlClicks
        };
        appendResults(result, i);         
      });
    }
  }

  function load() {
    gapi.client.setApiKey('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
    gapi.client.load('urlshortener', 'v1', makeRequest);
  }
</script>
<script src="https://apis.google.com/js/client.js?onload=load"></script>

the result would me different everytime! ex: shortUrl[1,2,3,4] it will return 3,2,1,4 or 1,2,4,3......etc

what's wrong is my code? is the async problem? how could i fix it? please help me! thx

Wayne Chu
  • 308
  • 1
  • 3
  • 11
  • instead of get() use $.ajax() with type:get and async:false – Sankara Feb 12 '14 at 14:06
  • 1
    @user8888 Just no, never. Forget that the `async: false` option even exists. – Anthony Grist Feb 12 '14 at 14:20
  • @AnthonyGrist I'd +1000 that comment if I could! – Alnitak Feb 12 '14 at 14:21
  • @AnthonyGrist: i will forget give me a reason – Sankara Feb 12 '14 at 14:25
  • oh `async: false` how I hate thee, let me count the ways.... 1. it causes the browser event loop to stall, 2. causing "page not responding errors", 3. It's *A*JAX goddammit, not *S*JAX! – Alnitak Feb 12 '14 at 14:28
  • @user8888 The main reason is that it blocks other code from executing, kind of removing the point of using AJAX in the first place. There's no reason not to make those four requests simultaneously (which is what AJAX allows you to do), if you start making each one block you have to wait for each one to complete before the next. – Anthony Grist Feb 12 '14 at 14:30
  • I'm rookie on js and jquery, glad to know any possible answer. But I don't know how to edit my code and let it work. Could you show me?? plz. – Wayne Chu Feb 12 '14 at 15:08

1 Answers1

2

Because ajax is asynchronous. You have to use promises. jQuery example.

var promises = [];
for (var i=0; i < shortUrl.length; i++){

  var dfd = new $.Deferred;

  var url = shortUrl[i];
  var request = gapi.client.urlshortener.url.get({
    'shortUrl': url,
    'projection':'FULL',
  });
  request.execute((function(dfd){return function(response) {
    dfd.resolve(response);      
  };})(dfd));

  promises.push(dfd.promise());
}

$.when.apply($, promises).done(function(){
  promises = undefined;
  for(var i in arguments){
    var response = arguments[i];
    console.log(response); //here is the problem begin
    var result = {
      short: response.id,
      clicks: response.analytics.allTime.shortUrlClicks
    };
    appendResults(result, i);  
  }
});

My working code:

var promises = [];

var request = function(i, callback){
setTimeout(function(){return callback(i);},100 - i);  
}

for (var i=0; i < 10; i++){

  var dfd = new $.Deferred;

  request(i, (function(dfd){return function(response) {
    dfd.resolve(response);      
  };})(dfd));

  promises.push(dfd.promise());
}

$.when.apply($, promises).done(function(){
  promises = undefined;
  for(var i in arguments){

    console.log(arguments[i]); 

  }
});
Peinguin
  • 85
  • 5
  • right idea, poor implementation... (e.g. `for var i in arguments` ?!) – Alnitak Feb 12 '14 at 14:23
  • my console: Uncaught TypeError: undefined is not a function – Wayne Chu Feb 12 '14 at 14:59
  • It's not working for me, is something wrong? @Alnitak What you mean? Is (for var i in arguments) is a bad way? – Wayne Chu Feb 12 '14 at 15:09
  • 1
    `for ... in` is for enumerating objects, not arrays. Also the resolve call could just be written `request.execute(dfd.resolve)` - the `response` parameter will still get passed and it'll be attached to the right `Deferred`. – Alnitak Feb 12 '14 at 15:12
  • I did not tested that code. when.apply must call done callback with all responses. – Peinguin Feb 12 '14 at 15:12
  • Please, try again. I mistake in Deferred. – Peinguin Feb 12 '14 at 15:23
  • the Uncaught TypeError erroe is fixed,thx. But it return nothing...@@ why? how to debug? – Wayne Chu Feb 12 '14 at 15:52
  • I guess it return nothing because my ahortUrl array's value is create by other function, and jQuery Deferred will prevent other code from interfering with the progress. is it? how could I fix it.... – Wayne Chu Feb 12 '14 at 16:14
  • Sorry. I fix code. I must pass deferred by link in new scope. – Peinguin Feb 13 '14 at 08:42
  • Thank you very much! This problem is fixed! But I got another ajax sync problem at http://stackoverflow.com/questions/21749552/i-set-ajax-async-false-but-not-working – Wayne Chu Feb 13 '14 at 09:10