LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-03-2015, 10:45 AM   #1
lmcilwain
Member
 
Registered: Dec 2003
Location: Maryland
Distribution: Fedora, Ubuntu, Centos, FreeBSD
Posts: 390

Rep: Reputation: 31
Question [JS Newbie] Having a hard time understanding a variable assignment issue


Hello all,

I have a feeling this is a super simple issue but I can't seem to figure out how to resolve it. I am attempting to write a JS method (using CoffeeScript) that calls data from a public API. I am able to retrieve the data but I am not able to assign it to a variable outside of the method for use.

In summary of my issue: after calling getWeather(city), this.city is still set to undefined

Any help would be greatly appreciated:

Here is the current code I am working with:
CoffeeScript:

Code:
  this.city = undefined
  this.getData = (city)->
    weather = getWeather(city)
    weather.done (result)->
      this.city = result
    .fail ->
      console.log(error)
      alert(error)
  undefined

getWeather = (city) ->
  promise = $.Deferred()
  $.ajax
    url: "http://api.openweathermap.org/data/2.5/weather"
    dataType: 'json'
    data:
      q: city
      APPID: "someAPIkey"
    success: (result) ->
      promise.resolve(result.main)
    error: ->
      promise.reject("Invalid Location")
  return promise
Which generates the following
Code:
   this.city = void 0;
   this.getData = function(city) {
      var weather;
      weather = getWeather(city);
      return weather.done(function(result) {
        return this.city = result;
      }).fail(function() {
        console.log(error);
        return alert(error);
      });
    };

 getWeather = function(city) {
    var promise;
    promise = $.Deferred();
    $.ajax({
      url: "http://api.openweathermap.org/data/2.5/weather",
      dataType: 'json',
      data: {
        q: city,
        APPID: "someAPIkey"
      },
      success: function(result) {
        return promise.resolve(result.main);
      },
      error: function() {
        return promise.reject("Invalid Location");
      }
    });
    return promise;
  };
 
Old 12-03-2015, 11:09 AM   #2
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 446Reputation: 446Reputation: 446Reputation: 446Reputation: 446
Hi

I'm not sure I understand completely, and don't know CoffeeScript. But the success and error callbacks that are sent to the ajax call shouldn't return anything. If they do, the return value is not assigned to anything. Also, ajax calls are asyncronous by default. That means the getWeather function returns first, the success or error functions are called later when the client get response from the server.

If you add "async:false" to the ajax call parameters, it doesn't return until you get data from the server. Then you can assign the result to a variable that you define in the getWeather function. And this variable you can return. But it's not a good solution. Nothing else can happen until you get response from the server, and that can take a long time. A better solution is simply to do whatever you need to do inside the success function.
 
Old 12-03-2015, 11:24 AM   #3
lmcilwain
Member
 
Registered: Dec 2003
Location: Maryland
Distribution: Fedora, Ubuntu, Centos, FreeBSD
Posts: 390

Original Poster
Rep: Reputation: 31
I was under the impression that .done() waits for $.ajax() to finish before executing its line of code. The .done() method associates with the promise.success() method and the .fail() method associates with the promise.error() method.

Maybe its time to scrap this code and start over and see what I am misunderstanding
 
Old 12-03-2015, 12:28 PM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
I am not all that familiar with js and only have learned a little coffee scripting (from rails), but even without any real understanding the script looks flawed.

If you look at the generated code, you set 'this.city' at the start, but the next time it 'looks' like it is getting set is inside a return value of a function. Thinking of most normal scopes,
if you are setting the value inside a function as a return value then it is never actually being assigned to your outer scope copy of the value.
Another weird part is in the empty function where you pass in 'result', you actually set your value and the returned item to the passed in item ... this also seems a little counter intuitive.

The above may be all wrong but it is just what it looks like to me
 
Old 12-03-2015, 04:42 PM   #5
lmcilwain
Member
 
Registered: Dec 2003
Location: Maryland
Distribution: Fedora, Ubuntu, Centos, FreeBSD
Posts: 390

Original Poster
Rep: Reputation: 31
Thanks for the help guys. I actually ended up having to go back to my code school course. They way they instructed was the following (lines in bold):

Code:
   this.city = void 0;
   some_var = this
   this.getData = function(city) {
      var weather;
      weather = getWeather(city);
      return weather.done(function(result) {
        return some_var.city = result;
      }).fail(function() {
        console.log(error);
        return alert(error);
      });
    };

 getWeather = function(city) {
    var promise;
    promise = $.Deferred();
    $.ajax({
      url: "http://api.openweathermap.org/data/2.5/weather",
      dataType: 'json',
      data: {
        q: city,
        APPID: "someAPIkey"
      },
      success: function(result) {
        return promise.resolve(result.main);
      },
      error: function() {
        return promise.reject("Invalid Location");
      }
    });
    return promise;
  };
I am planning to dig deeper into why I had to do it this way but my first guess would be that I am not understand stopes well so I should brush up on that.
 
Old 12-08-2015, 08:01 AM   #6
firstfire
Member
 
Registered: Mar 2006
Location: Ekaterinburg, Russia
Distribution: Debian, Ubuntu
Posts: 709

Rep: Reputation: 428Reputation: 428Reputation: 428Reputation: 428Reputation: 428
Hi.

Variable this in the following code
Code:
weather.done(function(result) {
  return this.city = result;
})
refers to the context of innermost anonymous function, not the context of its (grand-)parent function (where this.city variable was set). If you want to access parent context you either save it into a variable (like you did in your last post):
Code:
var self = this;
...
weather.done(function(result) {
  self.city = result;
});
or set the context of the inner function explicitly using bind (you'll have to do this twice because you have two-level function nesting). Most return statements in your code can be removed.

Anyway, the problem with such code is that you never know if the variable have meaningful value or not. If your code depend on correct value of the variable, you should either use callbacks (say, put your logic directly into success callback of ajax) or use promises. I will not try to review your code from the promise point of view, because the way you use them seems pointless to me -- just set the variable in success callback. Btw, I've heard jQuery promises are flawed, so avoid them if you can I prefer Q for promises, but there are lots of alternatives available. Nevertheless Q's documentation is a good starting point to learn about promises.

Good luck!

Last edited by firstfire; 12-08-2015 at 08:03 AM.
 
Old 12-10-2015, 11:03 AM   #7
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 446Reputation: 446Reputation: 446Reputation: 446Reputation: 446
Hi

When coding asyncronous stuff, hiding the complicated stuff in functions can just make problems. And it's not at all easier to read or understand. I think something like this is more clear:

Code:
<input type="text" id="city">
<script>

$("#city").on("change",function() {
    $.ajax({
      url: "http://api.openweathermap.org/data/2.5/weather",
      dataType: 'json',
      data: {
        q: $("#city").val(),
        APPID: "someAPIkey"
      },
      success: function(result) {
        // update the weather on the page. Put some text in a div or something?
        // you could add a function to parse and format the result, but why not put that code here?
      },
      error: function() {
        // display some error message or maybe do nothing?
      }
    });
});
</script>
 
  


Reply

Tags
coffeescript, javascript



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Question on variable naming and assignment... ${manintheyellowhat} Linux - Newbie 6 07-26-2010 07:41 PM
Variable assignment in Lisp. zaxonus Programming 2 03-18-2010 06:10 AM
[SOLVED] [BASH] variable assignment help RaptorX Programming 2 08-30-2009 10:28 AM
Java String variable re-assignment Cyhaxor Programming 9 11-24-2007 03:35 PM
Help understanding a C assignment. slzckboy Programming 3 02-22-2007 12:46 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:57 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration