Meteor call() callback receives undefined, why?


#1

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}`);
    }
  });

#2

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';
      }
    });

   },

#3

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()


#4

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: