Promises

A promise represents an action that's not completed yet. You can use a promise in a function to wait for an action to be completed. Callback functions attached to the promise fire when the promise is resolved (the action is done) or rejected (the action failed).

For example, suppose an app performs the following actions: When an agent attempts to save a ticket, the app intercepts the action with the save.ticket hook and makes an AJAX request to check something before allowing the ticket to be saved. You can use a promise to make the request while the ticket action awaits the outcome. Example:

checkProductBeforeSaving: function() {
    return this.promise(function(done, fail) {
        this.ajax('fetchProductID').then(
            function(data) {
                console.log('Request succeeded');
                // do something with the data
                done();     // ok to save the ticket
            },
            function() {
                console.log('Request failed');
                done();     // failed, but save the ticket anyway
            }
        );
    });
},

The then() method specifies handlers for the success and failure cases. Example: then(handlerDone, handlerFail).

See the Save Hook sample app on Github to learn more about using promises with hooks.

Zendesk apps support jQuery promises. See the jQuery promise documentation to understand how they work. In general, jQuery promises implement the Promises/A specification.

The following are examples of promises in apps.

Create and resolve a promise:

resolveAPromise: function() {
    this.promise(function(done, fail) {
        done();
    }).done(console.log.bind(console, 'All done!'));
}

Do something asynchronous before resolving:

resolveAPromise: function() {
    this.promise(function(done, fail) {
        setTimeout(function() { done(); }, 3000);
    }).done(console.log.bind(console, 'All done after 3 seconds!'));
}

Reject a promise:

rejectAPromise: function() {
    this.promise(function(done, fail) {
        fail();
    }).fail(console.log.bind(console, 'It failed!'));
}

Specify handlers for multiple events:

rejectAPromise: function() {
    this.promise(function(done, fail) {
        fail();
    }).fail(console.log.bind(console, 'All done!'))
        .always(console.log.bind(console, 'This will always fire!'));
}

Use then() to specify done and fail handlers. See deferred.then() on the jQuery website.

resolveAPromise: function() {
    this.promise(function(done, fail) {
        setTimeout(function() { done(); }, 3000);
    }).then(
        console.log.bind(console, 'All done after 3 seconds!'),
        console.log.bind(console, 'This would be if it failed!')
    );
}

Use when() to execute callback functions based on one or more Promise objects. See jQuery.when() on the jQuery website.

attachCallbacks: function() {
    var promise1 = this.ajax('getData'),
        promise2 = this.promise(function(done, fail) { done(); });

    this.when(promise1, promise2).then(
        console.log.bind(console, 'All promises have been resolved!'),
        console.log.bind(console, 'Some promise must have failed!')
    );
}
Passing arguments to done() or fail()

Any arguments passed to the done() or fail() methods are passed to any registered handlers in the same order.

Example:

resolveAPromise: function() {
    this.promise(function(done, fail) {
        setTimeout(function() { done('a', {}, 3); }, 3000);
    }).done(function(str, obj, num) {
        console.log(str === 'a');
        console.log(typeof obj === 'object');
        console.log(num === 3);
    });
}