简体   繁体   中英

Meteor synchronous call to function

Good Day. Been wracking the 'ol noggin for a way to solve this.

In a nutshell, I have a form that has a number of text inputs as well as an input file element to upload said file to AWS S3 (via lepozepo:s3 ver5.1.4 package). The nice thing about this package is that it does not need the server, thus keeping resources in check.

This S3 package uploads the file to my configured bucket and returns the URL to access the image among a few other data points.

So, back to the form. I need to put the AWS URL returned into the database along with the other form data. HOWEVER, the S3 call takes more time than what the app waits for since it is async, thus the field within my post to Meteor.call() is undefined only because it hasn't waited long enough to get the AWS URL.

I could solve this by putting the Meteor.call() right into the callback of the S3 call. However, I was hoping to avoid that as I'd much rather have the S3 upload be its own Module or helper function or even a function outside of any helpers as it could be reused in other areas of the app for file uploads.

Psudo-code:

Template.contacts.events({
  'submit #updateContact': function(e,template){
     s3.upload({file:inputFile, path:client},function(error,result){
       if(error){
         // throw error
       }else{
         var uploadInfo = result;
       }
     });
     formInfo = {name:$('[name=name]').val(),file:uploadInfo}; // <= file is undefined because S3 hasn't finished yet
     Meteor.call('serverMethod',formInfo, function(e,r){
         if(e){
           // throw error message
         }else{
           // show success message
         }
     });
});

I could put the formInfo and the Meteor.call() in the s3 callback, but that would result in more complex code and less code reuse where IMO this is a perfect place for code reuse.

I've tried wrapping the s3 in it's own function with and without a callback. I've tried using reactiveVars. I would think that updating the db another time with just the s3 file info would make the s3 abstraction more complex as it'd need to know the _id and such...

Any ideas? Thanks.

If you are using javascript it's best to embrace callbacks! What is it about using callbacks like this that you do not like, or believe is modular or reusable?

As shown below the uploader function does nothing but wrap s3.upload. But you mention this is psudeocode, so I presume that you left out logic you want included in the modular call to s3.upload (include it here), but decouple the logic around handling the response (pass in a callback).

uploader = function(s3_options, cb) {
  s3.upload(s3_options, function(error,result){
    if(error){
      cb(error);
    }else{
      cb(null, result);
    }
  });
};

Template.contacts.events({
  'submit #updateContact': function(e,template){

    cb = function(error, uploadInfo) {
      formInfo = {name:$('[name=name]').val(),file:uploadInfo};
      Meteor.call('serverMethod',formInfo, function(e,r){
      if(e){
        // throw error message
      }else{
        // show success message
      }
    });
  uploader({file:inputFile, path:client}, cb);  // you don't show where `inputFile` or `client` come from
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM