1

There is a simple field to input a youtube ID. I am using renaldo's youtube api (https://atmospherejs.com/renaldo/youtube-api) to retrieve the title of the youtube clip.

The client side event passes the track ID (var tid) value to the method 'addTrack' successfully - it outputs the track's title to the console on the server. I am having a really bad time returning anything at all back to the client.

If I call the 'getVideoData' method from the 'addTrack' method, it still returns 'undefined' every time. I am no expert in meteor or javascript, this is just something I am learning for the hell of it.

I understand the concept of callbacks and the synchronous nature of javascript (I think!).

Thanks.

[EDIT The code below solves my problem, using Future]

if (Meteor.isServer) {

  YoutubeApi.authenticate({
    type: 'key',
    key: API_KEY
  });

Meteor.methods({
  addTrack: function(tid) {

  Meteor.call("getVideoData", tid, function(err,res) {

    console.log(res);

    });
  },
  getVideoData: function(tid) {
    var future = new Future();

    YoutubeApi.videos.list({
    part: "snippet",
    id: tid,
  }, function (err,data) {
      var _data = {"title":data.items[0].snippet.title,"desc":data.items[0].snippet.description};
      future["return"](_data)

    });
    return future.wait();

}

Meteor.startup(function () { Future = Npm.require('fibers/future');

}); }

rick
  • 163
  • 4
  • This is a very common Meteor question that has several possible solutions. The basic issue is that your method is calling an asynchronous function. – Michel Floyd Apr 04 '16 at 01:17
  • How are you calling the method "getVideoData" from other methods, are you using Meteor.call("getVideoData")?? – Zafta Apr 04 '16 at 01:36
  • Yes, I am calling the method from another method via Meteor.call("getVideoData"), and still getting undefined. – rick Apr 04 '16 at 07:45
  • Is the working code above the best way to achieve the asynchronous callback in Meteor 1.3? – rick Apr 04 '16 at 09:31

1 Answers1

2

Meteor methods are tricky, as they use Fibers to be synchronous (well, they appear to the developer as synchronous). So you need to use Meteor.wrapAsync() to wrap the all to YoutubeApi. I haven't tested the following code, but it should look something like:

Meteor.methods({
  getVideoData: function(tid) {
    var syncYT = Meteor.wrapAsync(YoutubeApi.videos.list);
    var data = syncYT({part: "snippet",id: tid,});
    var transformed = {"title":data.items[0].snippet.title,"desc":data.items[0].snippet.description};

    console.log(transformed.title);
    return transformed.title;
  }
});

You'll want to read more about error handling in this case, but this should get you going. Just remember that client-side Meteor is always asynchronous and server-side is optionally asynchronous. Use wrapAsync or Futures to handle async needs in methods.

Lastly, the Meteor guide is great, use it!

DSK
  • 558
  • 4
  • 8