Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

180
Views
Why doesn't promise return from Lambda work while returning stream to handler for uploading to S3?

I want to return a stream from a function for the main Lambda handler to create a pipe. This works:

const { S3Client } = require("@aws-sdk/client-s3")
const { Upload } = require('@aws-sdk/lib-storage')
const stream = require('stream')
const s3Region = 'us-east-1'
const bucketname = "my_bucket"

exports.handler = function (event, context, callback) {
    let streamfrom = stream.Readable.from(["four"])
    getS3Stream()
        .then(streamto => {
            stream.pipeline(
                streamfrom,
                streamto,
                () => {
                    callback(null, { 'statusCode': 200 })
                })
        })
}

function getS3Stream() {
    return new Promise(resolve => {
        const pass = new stream.PassThrough()
        const upload = new Upload({
            client: new S3Client({ region: s3Region }),
            params: {
                Bucket: bucketname,
                Key: "test/test.txt",
                Body: pass
            }
        })
        upload.done().then((res, error) => {
            if (error) { reject(error) }
            console.log("s3 uploaded")
        })
        resolve(pass)
    })
}

But I want the handler function to return a promise instead of using a callback, at which point it no longer works:

exports.handler = async function (event, context) {
    return new Promise(resolve => {
        let streamfrom = stream.Readable.from(["five5"])
        getS3Stream()
            .then(streamto => {
                stream.pipeline(
                    streamfrom,
                    streamto,
                    () => {
                        resolve({ 'statusCode': 200 })
                    })
            })
    })
}

It returns {"statusCode":200}, but "s3 uploaded" is not printed, and the file does not appear in S3. Am I misunderstanding something about how to use promises here?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

If you want your handler to return a Promise, you have to mark it as async.

I have not found any documentation on this but I believe the runtime caller first checks the handler definition so it know how it should call it.

Something like:

if (handler.constructor.name === 'AsyncFunction') {
   result = await handler(event, context)
   handleResult(null, result)
} else if (handler.constructor.name === 'Function') {
   handler(event, context, handleResult)
} else {}

So, going back to your original code, it can be simply

exports.handler = async function (event, context) {
  return new Promise(resolve => {
    let streamfrom = stream.Readable.from(["five5"])
    getS3Stream()
      .then(streamto => {
        stream.pipeline(
          streamfrom,
          streamto,
          () => resolve({'statusCode': 200})
        )
      })
  })
}

function getS3Stream() {
  return new Promise(resolve => {
    const pass = new stream.PassThrough()
    const upload = new Upload({
      client: new S3Client({region: s3Region}),
      params: {
        Bucket: bucketname,
        Key: "test/test.txt",
        Body: pass
      }
    })
    upload.done().then((res, error) => {
      if (error) {
        reject(error)
      }
      console.log("s3 uploaded")
      resolve(pass)
    })
  })
}
about 4 years ago · Juan Pablo Isaza Report

0

Inspired by this I came up with a solution that almost meets my qualifications. The function doesn't return just the stream, it also returns the promise. I am still hoping someone will come up with something that works without that crutch.

const { S3Client } = require("@aws-sdk/client-s3")
const { Upload } = require('@aws-sdk/lib-storage')

const stream = require('stream');
const s3Region = 'us-east-1'
const bucketname = "my_bucket"

exports.handler = async function (event, context) {
    return new Promise(resolve => {
        let streamfrom = stream.Readable.from(["five5"])
        getS3Stream()
        .then(({streamto, promise})=>{
            stream.pipeline(
                streamfrom,
                streamto,
                () => promise.then(()=>resolve({ 'statusCode': 200 }))        
            )
        })
    })
}

async function getS3Stream() {
    const streamto = new stream.PassThrough()
    const s3Client = new S3Client({ region: s3Region })
    const upload = new Upload({
        client: s3Client,
        params: {
            Bucket: bucketname,
            Key: "test/test.txt",
            Body: streamto
        }
    })
    let promise = upload.done()
    return({streamto,promise})
}
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!