Mor Sagmon
Mor Sagmon

Reputation: 1045

Promise does not return any value to caller

I have an Angular app with a simple call to a service to upload an image to AWS S3. The upload service should return the AWS response to the caller. Despite the upload service successfully uploading the file and throwing the success message to the console, and despite a RETURN of the promise resolved, the caller "then" is not kickin in. There is no error messsage, only the following console.log statement is ignored:

console.log('aws file returned: ', res);

Here is the caller:

this.aws.uploadDataFile(data).then(res => {
      if (res) {
        console.log('aws file returned: ', res);
      }
    }, err => {
      console.log('error: ', err);
    });

Here is the upload service called:

uploadDataFile(data: any){
    const contentType = data.type;
    const bucket = new S3({
      accessKeyId: environment.awsAccessKey,
      secretAccessKey: environment.awsSecret,
      region: environment.awsRegion
    });
    const params = {
      Bucket: environment.awsBucket,
      Key: data.name, //manipulate filename here before uploading
      Body: data.value,
      ContentEncoding: 'base64',
      
      ContentType: contentType
    };
    return new Promise(function(resolve,reject){
      bucket.putObject(params, function(err, res) {
        if (err) { 
          console.log(err);
          console.log('Error uploading data: ', res); 
          return Promise.resolve(err);
        } 
        console.log('succesfully uploaded the image! ' + JSON.stringify(res));
        return Promise.resolve(res); 
      });
    })
  }

I do see the success message from the service in the console:

console.log('succesfully uploaded the image! ' + JSON.stringify(res));

But this message is not showing:

console.log('aws file returned: ', res);

I need the returned value in the caller to further perform tasks. What am I missing?

Upvotes: 0

Views: 563

Answers (2)

timmcb
timmcb

Reputation: 46

The Promise you are creating has an executor callback that provides the resolve and reject methods you should use to resolve the promise. Additionally, any return values from your executor are ignored. You can't chain onto the promise by returning a promise in the executor. This is documented on MDN for the Promise constructor.

The main issue is that you are not using the executor parameters to resolve or reject the promise. This leaves your promise in a pending state indefinitely. Invoking the appropriate resolve or reject will fix the issue.

function uploadDataFile(data) {
  //...
  return new Promise(function(resolve, reject) {
    bucket.putObject(params, function(err, res) {
      if (err) { 
        console.log(err);
        console.log('Error uploading data: ', res); 
        reject(err);
      } else {
        console.log('succesfully uploaded the image! ' + JSON.stringify(res));
        resolve(res); 
      }
    });
  });
}

In your case you are using the AWS API. So, you could use the built-in promise method from AWS. The promise method does the same conversion as above.

function uploadDataFile(data) {
  //...
  return bucket.putObject(params).promise().then(function(res) {
    console.log('succesfully uploaded the image! ' + JSON.stringify(res));
    return res;
  }).catch(function(err) {
    console.log('Error uploading data: '); 
    console.log(err);
    throw err;
  });
}

If you do not need the extra logging you can just return the promise.

function uploadDataFile(data) {
  //...
  return bucket.putObject(params).promise();
}

Upvotes: 2

Quentin
Quentin

Reputation: 944246

You're resolving the wrong promise.

Promise.resolve is a function which creates a new promise and immediately resolves it. It is extremely rare that it is actually useful.

It is not the same as the function which is passed by the Promise constructor function to your callback and placed in the first argument which you have named resolve.

You need to resolve that promise and not a new one.


Note that the AWS API has built-in support for promises so you don't need to promisify the callback function yourself anyway.

Upvotes: 1

Related Questions