How to convert callback sample to deferred object?

徘徊边缘 提交于 2019-12-08 19:39:33

问题


I have a function that accepts a callback function where I pass the data back in. Can this converted to a deferred object for better practice?

Here is what I got:

    var chapters;
    var getChapters = function (fnLoad) {
        //CACHE DATA IF APPLICABLE
        if (!chapters) {
            //CALL JSON DATA VIA AJAX
            $.getJSON('/chapters.txt')
                .done(function (json) {
                    //STORE DATA IN LOCAL STORAGE
                    chapters = Lawnchair(function () {
                        this.save(json, function (data) {
                            //CALL CALLBACK ON DATA
                            fnLoad(data);
                        });
                    });
                });
        } else {
            //RETURN ALREADY CREATED LOCAL STORAGE
            chapters.all(function (data) {
                //CALL CALLBACK ON DATA
                fnLoad(data);
            });
        }
    };

Then I simply use it like this:

this.getChapters(function (data) {
    console.log(data);
});

How can I use it like a promise though while maintaining the cache approach?

this.getChapters().done(function (data) {
    console.log(data);
});

回答1:


var chapters;
var getChapters = function (fnLoad) {
    var d = new $.Deferred();
    //CACHE DATA IF APPLICABLE
    if (!chapters) {
        //CALL JSON DATA VIA AJAX
        $.getJSON('/chapters.txt')
            .done(function (json) {
                //STORE DATA IN LOCAL STORAGE
                chapters = Lawnchair(function () {
                    this.save(json, function (data) {
                        //CALL CALLBACK ON DATA
                        d.resolve(data);
                    });
                });
            })
            .fail(function() { d.reject(); });
    } else {
        //RETURN ALREADY CREATED LOCAL STORAGE
        chapters.all(function (data) {
            //CALL CALLBACK ON DATA
            d.resolve(data);
        });
    }
    return d.promise();
};

Relevant example




回答2:


I see you have already accepted an answer, however if you take a large mental leap and store a promise of chapters instead of the chapters themselves, then the code will simplify significantly.

These days, this is probably the more generally adopted approach for a "fetch/cache" situation.

var chapters_promise;
var getChapters = function () {
    //Cache data if applicable and return promise of data
    if (!chapters_promise)
        chapters_promise = $.getJSON('/chapters.txt').then(Lawnchair).then(this.save);
    return chapters_promise;
};

What is actually promised (the chapters) will be determined by the value(s) returned by the functions Lawnchair and this.save, so you still have some work to do.

getChapters() will always return a promise, regardless of whether the data needs to be fetched or is already cached. Therefore, getChapters() can only be used with promise methods .then(), .done(), .fail() or .always(), for example :

getChapters().then(fnLoad);

You have no other way to access the chapters but that is reasonable since at any call of getChapters(), you don't know whether it will follow the $.getJSON() branch or the simple return branch, both of which return an identical promise.



来源:https://stackoverflow.com/questions/17639408/how-to-convert-callback-sample-to-deferred-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!