9

When using JQuery.Deferred is it OK to invoke reject() directly? Without having invoked a async function?

Perhaps I want some kind of test in the beginning of my async function. If the test fails I want to reject immediately. See the first if block below.

function doSomethingAsync() {

    //Test if the ajax call should be invoked
    var testFailed = true;

    var dfd = $.Deferred();

    //Check if test failed
    if (testFailed) {
        var asyncResult = {
            success: false,
            data: 'test failed'
        };

        //Is this OK usage of reject on the same thread?
        dfd.reject(asyncResult);

        return dfd.promise();
    }


    $.get('/api/testapi/get').done(function (data) {
        var asyncResult = {
            success: true,
            data: data
        };

        dfd.resolve(asyncResult);
    }).fail(function (err) {
        var asyncResult = {
            success: false,
            data: err
        };

        dfd.reject(asyncResult);
    });

    return dfd.promise();
}
Niclas
  • 217
  • 3
  • 9
  • 2
    Yes, it's ok to call `reject` when you want to reject. In fact this is a reason why this method exists. You still want your `doSomethingAsync` to return promise object, hence your approach is ok. In this case `doSomethingAsync().fail(callback)` will always work as expected. – dfsq Feb 02 '14 at 10:28
  • @dfsq Don't you want to make your comment to an answer? :) – zord Feb 02 '14 at 10:46
  • Thanks. I guess I don't know/understand how the Deferred object works. I just seems strange to invoke reject before the promise is returned, but it's great that I can =) – Niclas Feb 02 '14 at 11:49

2 Answers2

12

When using JQuery.Deferred is it OK to invoke reject() directly? Without having invoked a async function?

Yes, it's totally OK to return an already rejected promise, and to reject deferreds immediately. You only might need to verify that your callbacks don't rely on asynchronous resolution, which jQuery does not guarantee (in contrast to A+ implementations).

Notice that in your code you should use then instead of manually resolving the deferred:

function doSomethingAsync() {

    var testFailed = /* Test if the ajax call should be invoked */;

    var dfd = testFailed 
          ? $.Deferred().reject('test failed')
          : $.get('/api/testapi/get');

    return dfd.then(function (data) {
        return {
            success: true,
            data: data
        };
    }, function (err) {
        return {
            success: false,
            data: err
        };
    });
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks for the tip about using then. In which cases would I manually resolve the deferred? When not having another promise to use like a custom async method with a window.setTimeout? – Niclas Feb 03 '14 at 14:18
  • Yes, exactly. Or when you need to create a promise out of nowhere, like we've done for the `test failed`-rejection. But when you already have a promise around (like the one from `$.ajax`), you should always use `then` - error handlers, notifications, implicit arguments will automatically be handled and cannot be forgotten. – Bergi Feb 03 '14 at 17:57
0

You can do it quickly, as your function return a Promise object:

return Promise.reject('test failed');
Chouettou
  • 1,009
  • 1
  • 9
  • 10