Promise returning undefined when try to get link of image in functions firebase

Viewed 348

I'm trying to get the value of a response from a firebase function, however it is only returning me as undefined, I saw in some article that the body parser doesn't work anymore, I suspect the problem is in my function, but I'm not getting it find the problem, this is my function code, the image image is salve but don't return the 'imageUrl' to save in database

    exports.uploadImage = functions.https.onRequest((request, response) => {
    cors(request, response, () =>{
        try{
            fs.writeFileSync('tmp/imageToSave.jpg',
             request.body.image, 'base64')
            const bucket = storage.bucket('cloneinstagram-b46a9.appspot.com')
            const id = uuid()
            bucket.upload('tmp/imageToSave.jpg',{
                uploadType: 'media',
                destination: `posts/${id}.jpg`,
                metadata:{
                    metadata:{
                        contentType: 'image/jpeg',
                        firebaseStorageDownloadTokens:id
                    }
                }
            },( err, file) => {
                if(err){
                  console.log(err);
                    return response.status(500).json({error: err});
                }else{
                    const fileName = encodeURIComponent(file.name);
                    const imageUrl = 'https://firabasestorage.googleapis.com/v0/b/'+ bucket.name + '/o/' + fileName + '?alt=media&token=' + id;
                    return response.status(201).json({imageUrl: imageUrl})
                }
            }
        )
        }catch(err){
            console.log(err)
            return response.status(500).json({error:err})
        }
    })
 });

and this my mobile code

      axios({
            url: 'uploadImage',
            baseURL: 'https://us-central1-cloneinstagram-b46a9.cloudfunctions.net/',
            method: 'post',
            data:{
                image: posts.image.base64
            }
        })
            .catch(err => console.log('erro', err))
            .then(resp => { 
                posts.image = resp.data.image;
                console.log(' teste image',posts.image)
                axios.post('posts.json', {...posts})
                .catch(err => console.log('teste image', err))
                .then(res => console.log('teste imagem', (res.data.image))) 
            }) 
        }

@EDIT This code solved my problem

exports.uploadImage = functions.https.onRequest((request, response) => {
cors(request, response, () => {

    fs.writeFileSync('tmp/imageToSave.jpg', request.body.image, 'base64')
    const bucket = storage.bucket('cloneinstagram-b46a9.appspot.com')
    const id = uuid()

    bucket.upload('tmp/imageToSave.jpg', {
        uploadType: 'media',
        destination: `posts/${id}.jpg`,
        metadata: {
            metadata: {
                contentType: 'image/jpeg',
                firebaseStorageDownloadTokens: id
            }
        }
    })
        .then(uploadTaskSnapshot => {
            const fileName = encodeURIComponent(file.name);
            const imageUrl = 'https://firabasestorage.googleapis.com/v0/b/' + bucket.name + '/o/' + fileName + '?alt=media&token=' + id;
            return response.status(201).json({ imageUrl: imageUrl })
        })
        .catch(err => {
            console.log(err)
            return response.status(500).json({ error: err })
        })
});

});

1 Answers

As explained in the Cloud Functions doc, you need to deal with asynchronous processing by returning JavaScript promises.

So, in your case, you need to use the "Promised version" of the upload() asynchronous method, and not the "callback version".

As explained in the doc for this method (see the examples):

If the callback is omitted, (the method will) return a Promise.

So the following should do the trick:

exports.uploadImage = functions.https.onRequest((request, response) => {
    cors(request, response, () => {

        fs.writeFileSync('tmp/imageToSave.jpg', request.body.image, 'base64')
        const bucket = storage.bucket('cloneinstagram-b46a9.appspot.com')
        const id = uuid()

        bucket.upload('tmp/imageToSave.jpg', {
            uploadType: 'media',
            destination: `posts/${id}.jpg`,
            metadata: {
                metadata: {
                    contentType: 'image/jpeg',
                    firebaseStorageDownloadTokens: id
                }
            }
        })
            .then(uploadTaskSnapshot => {
                const fileName = encodeURIComponent(file.name);
                const imageUrl = 'https://firabasestorage.googleapis.com/v0/b/' + bucket.name + '/o/' + fileName + '?alt=media&token=' + id;
                return response.status(201).json({ imageUrl: imageUrl })
            })
            .catch(err => {
                console.log(err)
                return response.status(500).json({ error: err })
            })
    });

});

For more details on why you need, in Cloud Functions, to deal with asynchronous processing by returning Promises, I would suggest you watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/

Related