2

I'm trying to send an ajax call from the client to my server with data regarding an inputted parameter. When I attempt this, I am able to only see the data in my servers console, not in the browser.

Here in the client is the ajax call with "Peter_Abelard" setup as a demo title. This call gives me a 200 ok status but the response text is empty.

 $.ajax({
    type: "GET",
    url: 'http://localhost:3000/api/wiki/Peter_Abelard',
    async: false,
    datatype: 'json',
    success: function(response){
      console.log(response);
    }
  });

In the server code I have

function getData(name){
 wikipedia.page.data(name, { content: true }, function(response) {
  console.log(JSON.stringify(response));

  var dad = JSON.stringify(response);

  fs.writeFile("wikip.txt", dad, function(err) {
    if (err) throw err;
    console.log('It\'s saved!');
  });

  return dad;
});
}

app.get('/api/wiki/:que', function(req, res) {
  var queryd = req.params.que;
  getData(queryd);
  res.send(getData(queryd));
});

I believe this problem has something to with the line res.send(getData(queryd)) but I'm not sure what to try. If I am correct, this line should send the proper text to the client.

chackerian
  • 1,301
  • 2
  • 15
  • 29
  • 1
    from `getData(name)` instead of returning response return `dad` because in ajax you are requesting for 'json' but you are not sending one – Shubham Khatri Jul 25 '16 at 05:02
  • Just tried that and responseText is still blank. That is probably one step in the right path although. – chackerian Jul 25 '16 at 05:04
  • There are a couple things wrong here. First, your `getData()` function is asynchronous so it can't possibly return the result. Second, you are returning nothing from the actual `getData()` function. I'd suggest you read this [How to return the response from an asynchronous call](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call). – jfriend00 Jul 25 '16 at 05:05
  • Try and `console.log(getData(name))` in `app.get` and see what you get – Shubham Khatri Jul 25 '16 at 05:06
  • You mean switch out name with a name right? I tried that and it gave me the data. I don't think this is the issue however because I can successfully show data in the server just not in the client. – chackerian Jul 25 '16 at 05:19
  • 1
    FYI, I have no idea how anyone thinks that one character indentation makes readable code and makes it easy to see what level various things are at. I even have trouble reading code with two character indentation, so I always use four character indents as you will notice in my answer. – jfriend00 Jul 25 '16 at 05:28

1 Answers1

1

There are several things wrong with your current approach:

  1. There is no return value from the actual getData() function. That's why you always get undefined. You are returning from an inner callback, but that doesn't do anything.

  2. Your result is asynchronous so there's no way it can be returned from getData() because the result is not even known yet when getData() returns. An asynchronous response means that your Javascript continues to run (thus getData() returns empty handed) and the async callback is called sometime later.

  3. To make this work, getData() needs to either accept a callback which it can call when the data is available or it needs to return a promise and then the caller needs to use that callback or promise appropriately to get the data.

To make this work, you have to know how to handle asynchronous operation in node.js. I'd suggest this:

function getData(name, cb) {
    wikipedia.page.data(name, {content: true}, function (response) {
        console.log(response);

        cb(null, response);

        // I'm not sure why you're writing this here
        fs.writeFile("wikip.txt", dad, function (err) {
            if (err) throw err;
            console.log('It\'s saved!');
        });
    });
}

app.get('/api/wiki/:que', function (req, res) {
    var queryd = req.params.que;
    getData(queryd, function (err, data) {
        if (err) {
            // send error response here
        } else {
            res.json(data);
        }
    });
});

P.S. It looks very odd to me that wikipedia.page.data() has an async callback response, but no error reporting mechanism.

You can learn more about dealing with async operations in node.js by reading this answer: How do I return a response from an asynchronous operation.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I wrote to a file because I thought I might be able to use the file If I couldn't figure out how to send the data to the client directly. Thanks for still helping with my client server problems. What is cb btw? That makes it synchronous or something? – chackerian Jul 25 '16 at 05:13
  • `cb` is simply a callback in the getData method. It runs that method you pass as a second parameter to the getData method. `app.get(queryd, function(err, data){ ... )}`. It definetely doesn't make it synchronous but I am hoping @jfriend00 can mabe expand on how this approach fixes the problem with the callback I have had trouble understanding this approach as well. I have seen it used in multiple places :) –  Jul 25 '16 at 05:21
  • Since doesn't OP return `dad` in the third parameter passed to this method ` wikipedia.page.data(name, ..., func(res) { ... })` So essentially in this method `wikipedia.page.data` that third parameter the function will only be called after the data method gets the actual response so response should not be undefined and therefore `dad` shouldn't be undefined correct? –  Jul 25 '16 at 05:24
  • @chackerian - `cb` is a function reference passed as an argument to `getData()`. When `getData()` actually has the data at some future point in time that it was asked to fetch, it will call that function and pass it both an error value and/or the data. This is how you retrieve asynchronous results. It doesn't make it synchronous. It lets you work with the asynchronous result. – jfriend00 Jul 25 '16 at 05:25
  • @1290 - The OP's tiny indentation makes it hard to see, but `return dad` is inside the wiki callback. It's not the return value from `getData()`. There is no return value from `getData()`, thus it will always return `undefined`. – jfriend00 Jul 25 '16 at 05:26
  • @jfriend00 I tried using your solution but now my app is crashing throwing "TypeError: undefined is not a function" on the line with `cb(null, response);` – chackerian Jul 25 '16 at 05:28
  • 1
    @chackerian - Then, you didn't pass the right info to `getData()` when you were calling it. I can only help you with this version of your code if actually add it to your question so I could see exactly what you have. But, I think I put a full solution in my answer so you should be able to just copy that and use it. – jfriend00 Jul 25 '16 at 05:29
  • 1
    @1290 - Returning from the callback does nothing. That return value doesn't go anywhere. It's an asynchronous callback called from some networking event. `getData()` has long since returned already before that callback is even called. I'd suggest you read the link in my answer about returning a response from an async operation for more info. – jfriend00 Jul 25 '16 at 05:33
  • Ohh `getData()` doesn't return anything... stupid me he is returning from async callback. I just realzlied what you said about the indentation. Sorry about that! –  Jul 25 '16 at 05:34
  • @jfriend00 Yeah your right. I did implement your solution exactly as you indicated but I still had `res.send(getData(queryd));`. I commented this out and it now seems to work. Thanks for your time helping me deal with several issues. – chackerian Jul 25 '16 at 05:35