Nodal
Nodal

Reputation: 353

Using promises to return the result of an asynchronous function as a 'variable'

I'm having trouble with asynchronous execution in NodeJS. In particular, I have many use cases where I want to use the result of an asynchronous request much later in my code, and don't want to wrap the whole thing in another level of indentation such as an async.parallel.

I understand that the solution to this is using promises, but I am struggling to get the implementation right and the resources I have tried aren't helping.

My current problem is this: I need to get the _id of a MongoDB document immediately when it is inserted. I have switched from using MongoJS to using the official MongoDB driver as I was made aware that MongoJS does not support promises. Could anyone assist by providing a basic example of how to return this value using promises?

Thanks again.

Upvotes: 1

Views: 690

Answers (2)

chridam
chridam

Reputation: 103475

With the node.js driver, use the collection's insert() method which returns a promise. The following example demonstrates this:

var Db = require('mongodb').Db,
    MongoClient = require('mongodb').MongoClient,
    Server = require('mongodb').Server;   

var db = new Db('test', new Server('localhost', 27017));

// Fetch a collection to insert document into
db.open(function(err, db) {
    var collection = db.collection("post");

    // Create a function to return a promise
    function getPostPromise(post){
        return collection.insert(post);
    }

    // Create post to insert
    var post = { "title": "This is a test" },
        promise = getPostPromise(post); // Get the promise by calling the function

    // Use the promise to log the _id   
    promise.then(function(posts){
        console.log("Post added with _id " + posts[0]._id);    
    }).error(function(error){
        console.log(error);
    }).finally(function() {
        db.close();
    }); 
});

You can also use Mongoose's save() method as it returns a Promise. A basic example to demonstrate this follows:

// test.js
var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

// Establish a connection
mongoose.connect('mongodb://localhost/test', function(err) {
    if (err) { console.log(err) }
});

var postSchema = new Schema({
    "title": String
});

mongoose.model('Post', postSchema);

var Post = mongoose.model('Post');

function getPostPromise(postTitle){
    var p = new Post();
    p.title = postTitle;
    return p.save();
}

var promise = getPostPromise("This is a test");
promise.then(function(post){
    console.log("Post added with _id " + post._id);  
}).error(function(error){
    console.log(error);
});

Run the app

$ node test.js
Post added with _id 5696db8a049c1bb2ecaaa10f
$

Upvotes: 1

yunicz
yunicz

Reputation: 249

Well you can use the traditional approach with Promise.then(), or if you can use ES6, try generator functions (generators are included directly in Node, no runtime flag needed). This way, you could write simply this code:

//You can use yield only in generator functions
function*() {
    const newDocument = new Document({firstArg, SecondArg});
    const savedDocument = yield newDocument.save();
    //savedDocument contains the response from MongoDB

}

You can read more about function* here

Upvotes: 1

Related Questions