没有重构包装的jQuery $就落后一个门面在q.js [英] Wrapping jQuery $.ajax behind a facade in q.js without refactoring

查看:132
本文介绍了没有重构包装的jQuery $就落后一个门面在q.js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是可能的,这应该是在code审核,但在这里,我们走!

我有一个相当大的应用程序使用了大量的Ajax调用。我开始使用Q代表的一些异步的东西,想我会换Q中的AJAX调用,以确保所有异步方法具有相同的签名。

我使用的是一个全球性的立面的方法,因此我Ajax调用是这样的:

  App.ajax(配置)。然后(doWhatever);
 

与App.ajax看起来像这样:

  AJAX:功能(配置){
    VAR ajaxReturn = $。阿贾克斯(配置);
    ajaxReturn.error(函数(XHR){
        //一些自定义的错误处理
    });
    返回ajaxReturn;
}
 

我修改App.ajax看起来是这样的:

  AJAX:功能(配置){
    变种DFD = Q.defer();
    VAR ajaxReturn = $。阿贾克斯(配置);
    ajaxReturn.done(函数(结果,状态XHR){
        删除xhr.then;
        dfd.resolve(结果);
    });
    ajaxReturn.error(函数(XHR){
        //一些自定义的错误处理
        dfd.reject(错误处理产生了一些信息);
    });
    返回dfd.promise;
}
 

这个工作,需要对个人AJAX调用自己0的变化,但它造成的关心状态的Ajax调用和的$就返回XHR部分停止工作。

我读过 Q记者文档有关从jQuery的来了,它基本上只是表明你应该把诺言,返回像正常的同步功能功能,你应该假设他们只返回一个对象,

现在,我不希望有重构所有关心XHR对象可以接受一个对象或/将S $ P $垫,而不是那么做了电话。所以我说这code右键返回问答承诺之前:

  dfd.promise.then =函数(回调){
    dfd.promise.then = Q(),然后。
    返回dfd.promise.s $ P $垫(回调);
};
 

和改变了我的决心行:

  dfd.resolve(结果,状态XHR]);
 

和现在App.ajax看起来是这样的:

  AJAX:功能(配置){
    变种DFD = Q.defer();
    VAR ajaxReturn = $。阿贾克斯(配置);
    ajaxReturn.done(函数(结果,状态XHR){
        删除xhr.then;
        dfd.resolve(结果,状态XHR]);
    });
    ajaxReturn.error(函数(XHR){
        //一些自定义的错误处理
        dfd.reject(错误处理产生了一些信息);
    });
    dfd.promise.then =函数(回调){
        dfd.promise.then = Q(),然后。
        返回dfd.promise.s $ P $垫(回调);
    };
    返回dfd.promise;
}
 

因此​​,这是压倒一切的这个特定的递延当时用的包装功能,将重置再到真正的,那么与将S $ P $垫,而不是为这个通话功能。这导致我的应用程序的Ajax调用能够通过,并通过保留其原来的签名,但仍问答承诺。

这似乎做工精细,这是伟大的。

现在,终于,在问题但是,这是可取的?据我所知,在不必要的创造额外承诺在自定义,然后方法小的性能影响。我不关心这个。我更想知道是否有一些疑难杂症还没有咬我呢在哪里,这是严格意义上的非常糟糕的主意。

编辑:

有一些问题与上述的块。这是最先进的日期,code最正确的块。该承诺的然后不能只是​​重置为真正的然后,因为后续调用最初的承诺没有得到提供正常的S $ P $垫,所以我们要重新设置则方法回到凌驾中返回的新S $ P $垫诺言之前调用US $ p $垫。

  AJAX:功能(配置){
    变种DFD = Q.defer();
    VAR ajaxReturn = $。阿贾克斯(配置);
    ajaxReturn.done(函数(结果,状态XHR){
        删除xhr.then;
        dfd.resolve(结果,状态XHR]);
    });
    ajaxReturn.error(函数(XHR){
        //一些自定义的错误处理
        dfd.reject(错误处理产生了一些信息);
    });
    VAR cachedThen = dfd.promise.then;
    dfd.promise.then =功能overrideThen(完成,被拒绝){
        dfd.promise.then = cachedThen;
        变种US preadPromise = dfd.promise.s $ P $垫(满足,拒绝);
        dfd.promise.then = overrideThen;
        返回小号preadPromise;
    };
    返回dfd.promise;
}
 

解决方案

你这得太多。 Q被设计为互操作使用jQuery的承诺。

如果你想转换一个函数返回问答承诺 - 只是包装用 Q()

  myAjaxMethod(); //返回一个jQuery承诺
Q(myAjaxMethod()); //返回一个包装了jQuery 1问答承诺
 

因此​​,举例来说 - 你的 AJAX 的方法可以是:

 函数AJAX(配置){
    返回Q($阿贾克斯(配置)。);
}
 

这是短且不易出错。

It's possible this should be on code review, but here we go!

I have a fairly large application with a lot of ajax calls. I started using Q for some async stuff, and figured I would wrap the ajax calls in Q to ensure all async methods have the same signature.

I'm using a global facade method, so my ajax calls look like:

App.ajax( config ).then( doWhatever );

with App.ajax looking something like this:

ajax: function( config ){
    var ajaxReturn = $.ajax( config );
    ajaxReturn.error(function( xhr ){
        // some custom error handling
    });
    return ajaxReturn;
}

I modified App.ajax to look like this:

ajax: function( config ){
    var dfd = Q.defer();
    var ajaxReturn = $.ajax( config );
    ajaxReturn.done(function( results, status, xhr ){
        delete xhr.then;
        dfd.resolve( results );
    });
    ajaxReturn.error(function( xhr ){
        // some custom error handling
        dfd.reject( "some message generated by error handling" );
    });
    return dfd.promise;
}

This works, 0 changes needed on individual ajax calls themselves, but it caused the Ajax calls that cared about the "status" and "xhr" parts of the $.ajax return to stop working.

I've read Q's docs about coming from jQuery, and it basically just suggests "you should treat promise-returning functions like normal synchronous functions, in that you should assume they only return a single object"

Now, I didn't want to have to refactor all the calls that care about the xhr object to either take an object or use spread instead of then/done. So I added this code right before returning the Q promise:

dfd.promise.then = function( callback ){
    dfd.promise.then = Q().then;
    return dfd.promise.spread( callback );
};

and changed my resolve line to:

dfd.resolve( [ results, status, xhr ] );

and now App.ajax looks like this:

ajax: function( config ){
    var dfd = Q.defer();
    var ajaxReturn = $.ajax( config );
    ajaxReturn.done(function( results, status, xhr ){
        delete xhr.then;
        dfd.resolve( [ results, status, xhr ] );
    });
    ajaxReturn.error(function( xhr ){
        // some custom error handling
        dfd.reject( "some message generated by error handling" );
    });
    dfd.promise.then = function( callback ){
        dfd.promise.then = Q().then;
        return dfd.promise.spread( callback );
    };
    return dfd.promise;
}

So this is over-riding this specific Deferred's then function with a wrapper function that will reset then to the "real" then and use spread instead for this call. This results in my App ajax calls being able to retain their original signature, but still be a Q promise through and through.

This seems to work fine, and that's great.

now, finally, for the questions But is this advisable? I understand there's minor performance implications in unnecessarily creating the extra Promise in the custom "then" method. I don't care about that. I'm more wondering if there's some gotcha that hasn't bit me yet where this is strictly a very bad idea.

Edit:

There are some problems with the above block. This is the most up to date, most correct block of code. The promise's then can't just be reset to be the 'real' then, because subsequent calls to the initial promise don't get the proper spread result, so we have to reset the then method back to the over-ridden one that calls spread before returning the new spread promise.

ajax: function( config ){
    var dfd = Q.defer();
    var ajaxReturn = $.ajax( config );
    ajaxReturn.done(function( results, status, xhr ){
        delete xhr.then;
        dfd.resolve( [ results, status, xhr ] );
    });
    ajaxReturn.error(function( xhr ){
        // some custom error handling
        dfd.reject( "some message generated by error handling" );
    });
    var cachedThen = dfd.promise.then;
    dfd.promise.then = function overrideThen( fulfilled, rejected ){
        dfd.promise.then = cachedThen;
        var spreadPromise = dfd.promise.spread( fulfilled, rejected );
        dfd.promise.then = overrideThen;
        return spreadPromise;
    };
    return dfd.promise;
}

解决方案

You're overthinking it. Q is designed to interoperate with jQuery promises.

If you want to convert a function to return a Q promise - just wrap it with Q():

myAjaxMethod(); // returns a jQuery promise
Q(myAjaxMethod()); // returns a Q promise that wraps the jQuery one

So for example - your ajax method can be:

function ajax(config){
    return Q($.ajax(config));
}

Which is shorter and less error prone.

这篇关于没有重构包装的jQuery $就落后一个门面在q.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆