0

My uploadPhoto function should return the id (int) of the photo that has been uploaded.

so inside my main function I've got let photoId = await uploadPhoto(image, name);

here's the code of the uploadPhoto function: First attempt

async function uploadPhoto(image, name) {
    try {

        let file = fs.readFileSync( image );

        await client.uploadFile({
                    name: image,
                    type: "image/jpg",
                    bits: file
                }, function( error, data ) {
                    return data.id
                });

    } catch (err) {
        console.log(err);
    }
}

Second attempt

async function uploadPhoto(image, name) {
    try {

        let file = fs.readFileSync( image );

        function uploadF (callback){
             client.uploadFile(  { name: image, type: "image/jpg", bits: file } , function( error, data ) {
                return callback(data.attachment_id);
            });
        }

        let res = await uploadF(function (data){
           return data;
        });

    } catch (err) {
        console.log(err);
    }
}
6pounder
  • 67
  • 7
  • 1
    Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – David Jun 30 '22 at 11:45
  • @David thank you, I'm gonna read it and try to fix my code, you would help me a LOT if you could post an example with my code – 6pounder Jun 30 '22 at 11:47
  • Your example will depend heavily on what `client` is and whether `uploadFile` returns a `Promise` or only accepts a callback. If it returns a `Promise` then you can `await` its value and return it. If it only accepts a callback then you may have to manually wrap it in a `Promise` to return. – David Jun 30 '22 at 11:49
  • @David tried to remove the callback but it gave me an error, wish I could simply use await. If I remove the callback I get this error `return fn( null, data ); TypeError: fn is not a function` – 6pounder Jun 30 '22 at 11:53
  • There's nothing in the code shown called `fn`. It's not clear what you're expecting that line of code to do and why. – David Jun 30 '22 at 11:54
  • @David Using a library, it uploads to wordpress a photo, it returns photo id, name, etc. Not sure what fn is because I didn't write that function but I tried to `let response = await client.uploadFile( { name: image, type: "image/jpg", bits: file } ); ` and it gives me the error I've posted before – 6pounder Jun 30 '22 at 11:59
  • 2
    @David It sounds like `client.uploadFile` function mandates a callback and it seems to call the callback without checking if it exists. When OP left it out, the equivalent of `undefined(null, data)` was called which would lead to an error like that. – RickN Jun 30 '22 at 12:01
  • 1
    Ah, in that case it looks like you'd need to take the approach of wrapping it in a manual `Promise` and using `resolve` and `reject` internally, and returning that `Promise`. – David Jun 30 '22 at 12:03
  • 1
    Aside from the original question, since you're already using Promises, be sure to change your **`readFileSync`** to something that is **not sync**, like `const {readFile} = require('fs/promises');` + `const file = await readFile(image);` – RickN Jun 30 '22 at 12:17
  • 1
    Despite having your answer, I would encourage reading the answer that David shared. You'll be able to understand _why_ your code didn't work and _why_ the solution fixes it. You'll encounter callback- and Promise-based code a lot. – RickN Jun 30 '22 at 12:21

1 Answers1

2

Your uploadFile function doesn't return a Promise. That means that putting await in front won't make it wait until it's done. But you can wrap the function with a little bit of code so a Promise is returned.

// Call "resolve()" when the asynchronous action is done
// call "reject()" when an error occurs.
const data = await new Promise((resolve, reject) => {
  client.uploadFile({
    name: image,
    type: "image/jpg",
    bits: file
  }, function( error, data ) {
    if (error) {
      reject(error);
      return;
    }
    resolve(data.id);
  });
});
console.log(data.id);

Alternatively to wrapping it yourself, there is a helper function to do it for you:

const { promisify } = require('util');

// ...

// The .bind() might not be needed or it might be.
// Hard to tell without knowing what library you're using.
const upload = promisify(client.uploadFile).bind(client);

// ...

const data = await upload({
  name: image,
  type: "image/jpg",
  bits: file
});
console.log(data.id);
RickN
  • 12,537
  • 4
  • 24
  • 28