Skip to content
chris of the clan edited this page Jun 2, 2015 · 1 revision

How to use promises

Using promises is extremely simple for simple tasks, but it takes some time to cope with more complex usage.

Get two keys from virtualfs

First let's do it one after the other

function __doubleGet(params, customData, mod) {
	"use strict;"
	// don't edit above this line // must be on line 3
	var self = this; // save it for later
	
	return this.gamevfs.read(this.game.getPrivateDomain(), "keyA").then(function (keyA) {
	    // we have to use self instead of this here
	    return self.gamevfs.read(this.game.getPrivateDomain(), "keyB").then(function (keyB) {
	        return {keyA: keyA, keyB: keyB};
	    })
	});

}

Remember to ALWAYS return a promise ! Failing to do so is a bug: the promise would be garbage collected before we have a chance to get its value. Also, an exception would crash and never be returned to the client.

That's not optimal yet, because we could get both keys in parallel

function __doubleGet(params, customData, mod) {
	"use strict;"
	// don't edit above this line // must be on line 3
	
	var promiseForA = this.gamevfs.read(this.game.getPrivateDomain(), "keyA");
	var promiseForB = this.gamevfs.read(this.game.getPrivateDomain(), "keyB");
	
	return mod.Q.all([promiseForA, promiseForB]).then(function (arrayWithPromises) {
	    return {keyA: arrayWithPromises[0], keyB: arrayWithPromises[1]};
	});
	
}

We can use .spread instead of .then to make it even easier

function __doubleGet(params, customData, mod) {
	"use strict;"
	// don't edit above this line // must be on line 3
	
	var promiseForA = this.gamevfs.read(this.game.getPrivateDomain(), "keyA");
	var promiseForB = this.gamevfs.read(this.game.getPrivateDomain(), "keyB");
	
	return mod.Q.all([promiseForA, promiseForB]).spread(function (keyA, keyB) {
	    return {keyA: keyA, keyB: keyB};
	});
	
}

In all of these, we didn't have to handle errors... There's a .catch attached to the return value of your function which will help return the error if an exception is thrown.

We could modify the previous example to catch an error and return default values:

function __doubleGet(params, customData, mod) {
	"use strict;"
	// don't edit above this line // must be on line 3
	
	var promiseForA = this.gamevfs.read(this.game.getPrivateDomain(), "keyA");
	var promiseForB = this.gamevfs.read(this.game.getPrivateDomain(), "keyB");
	
	return mod.Q.all([promiseForA, promiseForB]).spread(function (keyA, keyB) {
	    return {keyA: keyA, keyB: keyB};
	}).catch(function (error) {
	    // will return default if either key was missing
	    return {keyA: 'default', keyB: 'default'};
	});
}

If the number of promises is variable, you can Array.push() them one by one in an array and pass it to Q.all.

As you grow more confortable with promises, you'll find plenty of information in the Bluebird API docs.

To make it easier to debug, use mod.debug() in your code. Your hook/batch will log into the batch editor in the Backoffice. Note that hook/batch logging is disabled in production.

function __doubleGet(params, customData, mod) {
	"use strict;"
	// don't edit above this line // must be on line 3
	
	var promiseForA = this.gamevfs.read(this.game.getPrivateDomain(), "keyA");
	var promiseForB = this.gamevfs.read(this.game.getPrivateDomain(), "keyB");
	
	return mod.Q.all([promiseForA, promiseForB]).spread(function (keyA, keyB) {
	    mod.debug("Got both keys A and B");
	    return {keyA: keyA, keyB: keyB};
	}).catch(function (error) {
	    // will return default if either key was missing
	    mod.debug("There was an error");
	    return {keyA: 'default', keyB: 'default'};
	});
}

Clone this wiki locally