Rewrite Promise using async / await

Hi, can anyone help me rewrite this function using async / await instead of a Promise?

function uploadToS3(req, res) {
  req.s3Key = uuidv4()

  let downloadUrl = `https://caltekshopbucket1.s3-us-west-2.amazonaws.com/${req.s3Key}`

  return new Promise((resolve, reject) => {
    return singleFileUpload(req, res, err => {
      if (err) return reject(err)
      return resolve(downloadUrl)
    })
  })
}

I found a nice article that can do just that.

I tried this but it doesn’t work:

const uploadToS3 = async (req, res) => {
  try {
    req.s3Key = uuidv4()
    let downloadUrl = `https://caltekshopbucket1.s3-us-west-2.amazonaws.com/${req.s3Key}`
    await singleFileUpload()
    return downloadUrl
  } catch (error) {
    console.log(error)
  }
}

Can you give us more details on exactly what you mean by “it doesn’t work”? Are you getting any console errors?

Also, I’m not familiar with the function singleFileUpload. Why is it being passed in arguments in the original version but not in the updated version?

I think it’s ok to just think of singleFileUpload() as randomFunctionReturningSomething().

In the Promise, this function is called. It uploads a file and returns a response. The promise says that once the file upload completes, the parent function (upoloadToS3) should simply return a string containing a download URL.

If you want to see the full code, I’ll paste it below. The code works, I just wanted to remove the Promise as the rest of my app uses async/await instead of Promises.

import aws from "aws-sdk"
import express from "express"
import multer from "multer"
import multerS3 from "multer-s3"
import asyncHandler from "express-async-handler"
import { v4 as uuidv4 } from "uuid"

aws.config.update({
  bucketName: "caltekshopbucket1",
  secretAccessKey: "Gu0A5F1vYi/2+DMM1nK9JFyCr7v2D35XmM5x96ae",
  accessKeyId: "AKIAWLZFTWX3VMSNWAUC",
  region: "us-west-2"
})

const s3 = new aws.S3()

const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: "caltekshopbucket1",
    metadata: function(req, file, cb) {
      cb(null, { fieldName: file.fieldname })
    },
    key: function(req, file, cb) {
      cb(null, req.s3Key)
    }
  })
})

const singleFileUpload = upload.single("image")

function uploadToS3(req, res) {
  req.s3Key = uuidv4()
  let downloadUrl = `https://caltekshopbucket1.s3-us-west-2.amazonaws.com/${req.s3Key}`
  return new Promise((resolve, reject) => {
    return singleFileUpload(req, res, err => {
      if (err) return reject(err)
      return resolve(downloadUrl)
    })
  })
}

export const uploadImage = asyncHandler(async (req, res) => {
  uploadToS3(req, res)
    .then(downloadUrl => {
      return res.status(200).send(downloadUrl)
    })
    .catch(e => {
      console.log(e)
    })
})

//process.env.S3_ACCESS_KEY_ID
//process.env.S3_SECRET_ACCESS_KEY

Async/await is a replacement for then, not the creation of a Promise.

/* with then/catch */
export const uploadImage = asyncHandler((req, res) => {
  uploadToS3(req, res)
    .then(downloadUrl => {
      return res.status(200).send(downloadUrl)
    })
    .catch(e => {
      console.log(e)
    })
})
/* with async/await and a trycatch block */
export const uploadImage = asyncHandler(async (req, res) => {
  try {
    const downloadUrl = await uploadToS3()
    return res.status(200).send(downloadUrl)
  } catch(e) {
    console.log(e)
  }
})

You rewrote the wrong function. I want to rewrite this function using async / await. Or are you saying this is impossible?:

function uploadToS3(req, res) {
  req.s3Key = uuidv4()
  let downloadUrl = `https://caltekshopbucket1.s3-us-west-2.amazonaws.com/${req.s3Key}`
  return new Promise((resolve, reject) => {
    return singleFileUpload(req, res, err => {
      if (err) return reject(err)
      return resolve(downloadUrl)
    })
  })
}

Right, what I’m saying is there are no promises to await in that block of code.

return new Promise((resolve, reject) => {
  return singleFileUpload(req, res, err => {
    if (err) return reject(err)
    return resolve(downloadUrl)
  })
})

This block right here is wrapping the callback-based asynchronous upload function in a Promise, so that you can await it later, as I showed in my last comment. Again, await is a replacement for chaining then.

I just looked back at your initial question. await is an API used for interacting with promises (it literally waits for the result of the promise, then continues execution), so the premise of your question doesn’t really make sense.

I think your explanation finally penetrated my thick skull… Thanks!

For anyone else confused about Promises, I figured out what was so puzzling to me. In Javascript, the fetch API alread has a built in Promise, so you can use .then with it, without seeing any “Promise” text in any code. Axios and Mongoose also have built in Promises. This caused me to be very confused about when I could and couldn’t use “.then”.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.