Meteor call() callback receives undefined, why?

I’m a bit confused why this code is not working. Shouldn’t this work? When we put a return outside of the cloudinary function callback it works, when within the callback of cloudinary it isn’t. But shouldn’t it? I understand that cloudinary is waiting for the callback to be run, which IS happening. But when we do a return to exit the method, it’s actually returning undefined.

On the server:

  imageUpload: function (imageFile) {
    // this works
    // return 'bla';
    cloudinary.v2.uploader.upload('https://www.houseme.space/img/hero_image.jpg',{
      crop: 'limit', width: 400, height: 400, tags: ['profileImages'], folder: 'profileImages',
    }, (err, res) => {
      if(err) {
        console.log(err);
      } else {
        // this does not
        return 'bla';
      }
    });

   },

On the Client:

  Meteor.call('imageUpload', file, (err, res) => {
    if(err) {
      console.log(`error is ${err}`);
      return;
    } else {
      console.log(`result is ${res}`);
    }
  });

This is probably your problem:

You’re just logging an error but not returning anything, so undefined is returned. The correct way of handling this is:

  imageUpload: function (imageFile) {
    // this works
    // return 'bla';
    cloudinary.v2.uploader.upload('https://www.houseme.space/img/hero_image.jpg',{
      crop: 'limit', width: 400, height: 400, tags: ['profileImages'], folder: 'profileImages',
    }, (err, res) => {
      if(err) {
        throw new Meteor.Error('upload-failure', 'Image upload failure');
      } else {
        // this does not
        return 'bla';
      }
    });

   },

That’s true, I could have thrown an error. But there’s no error, it’s successful, meaning the successful else condition is actually being executed.

In other words:

  imageUpload: function (imageFile) {
    // this works
    // return 'bla';
    cloudinary.v2.uploader.upload('https://www.houseme.space/img/hero_image.jpg',{
      crop: 'limit', width: 400, height: 400, tags: ['profileImages'], folder: 'profileImages',
    }, (err, res) => {
      if(err) {
        throw new Meteor.Error('upload-failure', 'Image upload failure');
      } else {
        // this does not
        console.log('bla');
        return 'bla';
      }
    });

   },

console.log(‘bla’) will be logged on the server but the return doesn’t return anything to our callback when we do the Meteor.call()

Oh! Of course. You can’t have an async operation like that on the server side, not without making it synchronous. Try this:

const cloudinaryUploadSync = Meteor.wrapAsync(cloudinary.v2.uploader.upload);

Meteor.methods({
  imageUpload: function (imageFile) {
    const result = cloudinaryUploadSync('https://www.houseme.space/img/hero_image.jpg',{
      crop: 'limit', width: 400, height: 400, tags: ['profileImages'], folder: 'profileImages',
    });
  },
  //...

If the upload encounters an error, I think it will throw an error on its own. Maybe. You may wanna also try wrapping the upload call in a try/catch to check.

If I had had my cup of coffee, I would’ve figured this out the first time. :wink:

1 Like