2

I'd like to use Bluebird's promisify function on an AWS putItem function. Notice from the docs that it returns an AWS.Request object. I am not interested in that object and ideally I would just call db.putItem({...}); and get a Promise back. Is this possible? When I tried it, the promisify'd function still returns an AWS.Request object, which I suppose is reasonable, it's just not what I want in this case.

For the time being I am just creating a Promise object and manually mapping the success and error data to the resolve/reject promise functions, but it feels like I'm writing unnecessary boilerplate code, since aside from that return value, the putItem function (and may of the other functions) seems well suited for promisify.

As requested, here are the relevant parts of the code:

//datastore.js

var AWS = require('aws-sdk');

var sharedDB;

if (!sharedDB) {
    AWS.config.update({accessKeyId: 'akid', secretAccessKey: 'secret', region: "us-west-2"});
    sharedDB = new AWS.DynamoDB();
    sharedDB.setEndpoint("http://localhost:8000");
    Promise.promisify(sharedDB.putItem); 
}

module.exports.sharedDB = sharedDB;

//user.js

var db = require('../datastore/dynamoDBConnection').sharedDB;
var Promise = require("bluebird");


function User() {
var user = this;
...

user.save = function () {
        var params = {
            Item: {
                username: {S: 'test'},
                passwordHash: {S: 'test'}
            },
            TableName: 'users',
            Expected: {
                username: {Exists: false}
            }
        };
        return db.putItem(params); //this is where I would like have a Promise returned.  Instead I get an AWS.Request object.
}
...
}
user605331
  • 3,718
  • 4
  • 33
  • 60
  • possible duplicate of [How do I convert an existing callback API to promises?](http://stackoverflow.com/questions/22519784/how-do-i-convert-an-existing-callback-api-to-promises) – Benjamin Gruenbaum May 17 '14 at 15:21
  • While there is a lot of detail there, that post is missing the specific use case I am asking about though, which is using promisify on a function that uses callbacks, but also returns a value. – user605331 May 17 '14 at 16:34
  • I think I can reworded my question in the context of your answer to the referenced answer: From the 3rd option, can I still do "Promise.promisify(getStuff);" if the getStuff function were to also have a return value? – user605331 May 17 '14 at 16:49
  • What kind of value does it return? Does it call the callback back with an error and a result? If not, how does it communicate an error happened? – Esailija May 17 '14 at 18:34
  • The promisify'd function returns a AWS.Request object, not a Promise. I don't recall if it calls the callback, I was focusing on getting the promise object to work with. I'll run a test again later and see. – user605331 May 17 '14 at 23:08
  • 1
    Promisify _returns_ the modifies function, it doesn't alter it in place – Benjamin Gruenbaum May 18 '14 at 13:49
  • Ah, thanks @benjamin-gruenbaum. Doing that does the trick, although it seems to break the function in some other way ('Possibly unhandled TypeError: Object # has no method 'makeRequest''). Still, this answers my question. The AWS-specific stuff is separate from this and I'll deal with that on its own. – user605331 May 18 '14 at 13:58
  • I have a question on Promise.promisify .please solve it http://stackoverflow.com/questions/30860857/avoiding-callback-hell-using-generators-and-promises-co-module – Ayush Bansal Jun 24 '15 at 07:20

1 Answers1

4

Update

You're using Promisify wrong, it returns the promisified function.

var putItemAsync = Promise.promisify(sharedDB.putItem); 

And use putItemAsync. Also, you should only call promisify once and cache it.


PutItem takes a callback, but it resolves with a stream, so promisifying it is a little tricker than usual.

return new Promise(function(resolve,reject){
    dynamoDB.putItem(
    {"TableName":"Table1",
        "Item":{
            "Color":{"S":"white"},
            "Name":{"S":"fancy vase"},
            "Weight":{"N":"2"}
        }
    }, function(result) {
        var wholeResult = [];
        result.on('data', function(chunk){
            wholeResult.push(chunk);
        });
        result.on('end', function(){ resolve(Buffer.concat(wholeResult))});
        result.on('error', function(e){ reject(new Error(e)); });
    });
});
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Perhaps I should have been more specific. I'm using the dynamoDB api, which does not stream the results. It just provides a deserialized object. – user605331 May 17 '14 at 16:32
  • @user605331 so what's wrong with just `Promise.promisify(getStuff)` ? – Benjamin Gruenbaum May 17 '14 at 20:33
  • That's what I assumed I could so, but when I do that and then call the modified function it returns back that AWS.Request object, not a Promise. – user605331 May 17 '14 at 23:04
  • I apologize for not posting the code with the original question. I thought this was something where the function docs were enough to know if it would work or not. It seems this is more complex than I thought. Question updated with code. – user605331 May 18 '14 at 13:46