Method with Promise does not wait for .all and returns to fast


#1

Hi,

In my client I have a generate app button, for each template for each customer it should do something.

It works and I receive the return of my promise chain (after 10 seconds or so), But In the user screen I get the result immediately. Do you maybe see why?

Client calls method, method call generate function and should return the promise if

  • For each customer
  • For each app
    have all resolved (notice I have implemented a for each loop using the map function)

client

'click .generateStreamAndApp'() {
    console.log('click event generateStreamAndApp');
    
    var selectedCustomers = Customers.find({checked: true}).fetch();
    // console.log('get customers from database, and pass them to the generateStreamAndApp method', selectedCustomers);

    Meteor.call('generateStreamAndApp',selectedCustomers,templateGuid, function(err, result) {
      if (err) {
        sAlert.error(err);
        console.log(err);
      } else  {
        console.log('generateStreamAndApp succes', result);
        sAlert.success('Streams and apps created, and apps have been published into the stream of the customer ');
        updateSenseInfo();
      }
    });

server generate method

Meteor.methods({  
	generateStreamAndApp (customers) {
		check(customers, Array);
		generateStreamAndApp(customers)
		.then(
			function fulfilled (result) {
				console.log('generation promise fulfilled, result of promise', result);
				// resolve('Generation success ');
				return 'Generation success';
			},
			function Rejected (error){
				console.error('Promise Rejected: Error when trying generate the apps', error);
				throw new Meteor.Error('Generation failed','Promise Rejected: Error when trying to generate the apps');
			})
	},

server generate function

/*
//	//for each customer
	//create stream if not already exist
	//copy app
	//publish to stream
	//add 'generated' tag
	*/
	function generateStreamAndApp (customers) {
		console.log('METHOD called: generateStreamAndApp for the template apps as stored in the database of the fictive OEM');

		var templateApps = TemplateApps.find().fetch();
	if(!TemplateApps.find().count()){//user has not specified a template
		throw new Meteor.Error('No Template', 'user has not specified a template for which apps can be generated');
	} 
	if(!customers.length){ // = 0
		throw new Meteor.Error('No customers', 'user has not specified at least one customer for which an app can be generated');
	} 

//FOR EACH TEPMPLATE
var generationEndedPromise =  Promise.all(_.map(templateApps, function(templateApp){
		console.log('the current template app: ', templateApp.name);

	//FOR EACH CUSTOMER
	return Promise.all(_.map(customers, function(customer){	
		console.log('############## START CREATING THE TEMPLATE '+templateApp.name+' FOR THIS CUSTOMER: '+customer.name);

		var stream = Streams.findOne({name:customer.name});  //Find the stream for the name of the customer in Mongo, and get his Id from the returned object
		if(stream){
			var streamId = stream.id;
		}
		// console.log('!!! The stream Id found is: ',streamId);			
		var myPromise = new Promise(function(resolve, reject) {
			if(!streamId){ 
				console.log('No stream for customer exist, so create one: '+customer.name);
				createStream( customer.name)
				.then(
					function fulfilled (result) {
						// console.log('stream create promosi fulfilled, result of create stream promise', result);
						streamId = result.id;
						resolve('created stream with id '+result.id);
					},
					function Rejected (error){
						// console.error('Promise Rejected: Error when trying to copy the app', error);
						reject('Promise Rejected: Error when trying to create a stream');
					})
			} else{
				// console.log('No need to create a stream, because it already exists: '+Streams.findOne({name:customer.name}).count()+' time(s)');
				resolve('No need to createa a stream, already exists'+Streams.find({name:customer.name}).count()+' time(s)');
			} 
		})
		.then(function(resultOfStreamStep){ //Copy the APP
			console.log('2 COPY the app: result Of create Stream Step: ', resultOfStreamStep);
			return copyApp(templateApp.guid, customer.name+' - ' + templateApp.name)
		})
		.then(function(appGuid){ //Publish into streamId
			console.log('3 PUBLISH: APP HAS BEEN COPIED AND HAS RECEIVED GUID', appGuid);
			return publishApp(appGuid, templateApp.name, streamId) //return publishApp(appGuid, templateApp.name+' - ' +customer.name , streamId)
		})
		.then(function(){
			console.log('############## FINISHED CREATING THE TEMPLATE '+templateApp.name+' FOR THIS CUSTOMER: '+customer.name);
			console.log('	');
		})		
		.catch(function(err) {
			console.error(err);
			// throw new Meteor.Error('Catch error app generation chain: App generation failed', 'err');
		}).done();	
		return myPromise;

	})) //each template Promise.all
	}) //each customer
	) //promise all generation total

return generationEndedPromise;
};

#2

ok, solved

Watch out, In my call to meteor method I passed 1 parameter too much (in the middle) so apparently that is not allowed. I would have expected it did not matter, because the callback is always the last oneā€¦ right?