Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #8998

Re: How to Create an XHR (Ajax) Object

Message-ID <1810376.7NaK4W3vae@PointedEars.de> (permalink)
From Thomas 'PointedEars' Lahn <PointedEars@web.de>
Organization PointedEars Software (PES)
Date 2011-12-08 23:12 +0100
Subject Re: How to Create an XHR (Ajax) Object
Newsgroups comp.lang.javascript
References <c8822aed-a1a2-4009-a65d-686b79090c3e@s26g2000yqd.googlegroups.com> <jbpf64$d8r$1@news.albasani.net>
Followup-To comp.lang.javascript

Followups directed to: comp.lang.javascript

Show all headers | View raw


Andreas Bergmaier wrote:

> David Mark schrieb:
>> How to Create an XHR (Ajax) Object
>>
>> var xhrCreated;
>>
>> // As always, shorthand feature detection for example--use
>> isHostMethod in this case
>>
>> // Degrades in IE 6- :)
>>
>> if (this.XMLHttpRequest)
>>    // Use try-catch as this host object may explode on creation
>>
>>    try {
>>      var x = new XMLHttpRequest();
>>      xhrCreated = true;
>>    } catch(e) {
>>    }
>> }
>>
>> if (xhrCreated) {
>>    var createXhrObject = function() {
>>      return new XMLHttpRequest();
>>    };
>> }
>>
>> if (createXhrObject) {
>>    // Put app that must create XHR objects here
>> }
>>
>> In my experience, such IE fallback scripts are usually aimed at 8 and
>> under, but this one is only needed for 6 and under, so do this:-
>>
>> if (!createXhrObject) {
>>    // Create ActiveX rendition here
>> }
> 
> What do you think about
> 
> if (!window.XMLHttpRequest)
>     window.XMLHttpRequest = function() {
>        try {
>           return new (window.XMLHttpRequest = function XMLHttpRequest() {
>              ActiveXObject.call(this, "Microsoft.XMLHTTP");
>           });
>        } catch(e) {
>           try {
>              return new (window.XMLHttpRequest = function XMLHttpRequest()
>              {
>                 ActiveXObject.call(this, "Msxml2.XMLHTTP");
>              });
>           } catch(e) {
>              delete window.XMLHttpRequest;
>              throw new Error("This browser doesn't support any AJAX");
>           }
>        }
>     };
> 
> And then just use new XMLHttpRequest() whereever you need it?

I think it is utter nonsense.  I wonder, have you even tried it?

- You are testing a property of the object referred to by `window' when you
  are interested in a property of the global object.

- You are attempting to augment the host object referred to by `window'.

- Calling a callable object as property of another object is _not_
  equivalent to using it as a constructor.

- You are calling `call' on a host object, but it does not need to inherit
  from Function.prototype or otherwise implement that method.  Since
  `ActiveXObject' implements the method, but does not allow it to be called
  on that object ("Automation server cannot create object"), assuming that
  no other host-object specific peculiarities are involved, the first
  attempt to use `new window.XMLHttpRequest' will delete
  `window.XMLHttpRequest' and throw an Error exception; if that exception
  is handled, subsequent attempts will throw a built-in TypeError exception.  

- The `call' call is pointless.  Your constructor does _not_ *return* a
  reference to another object (as a factory would), so it returns a
  reference to an "empty" Object instance:

    return new (window.XMLHttpRequest = function XMLHttpRequest() {
      ActiveXObject.call(this, "Microsoft.XMLHTTP");
    });

  evaluates to

    window.XMLHttpRequest = function XMLHttpRequest() {
      ActiveXObject.call(this, "Microsoft.XMLHTTP");
    };

    return new window.XMLHttpRequest();

  which, assuming for a moment `call' works here, can be broken down into

    var previousXHR = window.XMLHttpRequest;

    window.XMLHttpRequest = function XMLHttpRequest() {
      ActiveXObject.call(previousXHR, "Microsoft.XMLHTTP");
    };

    return new window.XMLHttpRequest();

  which evaluates to the equivalent of

    return {};

  As a result, attempts to call XHR methods on the newly created object will
  throw a built-in TypeError exception, while attempts to set event
  listeners or other non callable properties will probably work but will do
  nothing useful.

  In case you have problems seeing any of the above, replace the relevant
  parts with dummy parts that work basically the same:

  var w = {},
      global = this;

  function A ()
  {
    console.log("A: ", arguments);

    /* Disable this to see what happened if call() would work */
    if (this != global)
    {
      throw new Error("Automation server cannot create object");
    }
  }

  A.prototype.open = function () {};
  
  if (!w.X)
    w.X = function () {
      try
      {
        return new (w.X = function X () {
          A.call(this, "Microsoft.XMLHTTP");
        });
      }
      catch (e) {
        try
        {
          return new (w.X = function X () {
            A.call(this, "Msxml2.XMLHTTP");
          });
        }
        catch (e)
        {
          delete w.X;
          throw new Error("This browser doesn't support any AJAX");
        }
      }
   };

   /* Disable this to see what happened if exception was not handled */
   try
   {
     new w.X();
   }
   catch (e)
   {
   }

   var x = new w.X();

   /* TypeError */
   x.open();

- You are using a named function expression.  Doing that, you are
  effectively declaring a function with that name in the local execution
  context, due to a JScript bug (which is the ECMAScript implementation of
  about the only environment that this code would be relevant for).  This is
  even more foolish as you are not referring to the function name in the
  function (recursion without arguments.callee).

- The `XMLHttpRequest' behavior in JScript/MSHTML varies from that in MSXML,
  and might even vary more from it in the future (when XMLHttpRequest2 might
  be implemented).  So you need to encapsulate this.  (ISTM David's original
  approach already falls short of that distinction.)

So you *really* do *not* want to do this.


PointedEars
-- 
    realism:    HTML 4.01 Strict
    evangelism: XHTML 1.0 Strict
    madness:    XHTML 1.1 as application/xhtml+xml
                                                    -- Bjoern Hoehrmann

Back to comp.lang.javascript | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

David Mark's Daily Javascript Tips  - Volume #3 - Tip #10 - How to Create an XHR (Ajax) Object David Mark <dmark.cinsoft@gmail.com> - 2011-12-07 15:36 -0800
  Re: How to Create an XHR (Ajax) Object Andreas Bergmaier <andber93@web.de> - 2011-12-08 05:41 +0100
    Re: How to Create an XHR (Ajax) Object David Mark <dmark.cinsoft@gmail.com> - 2011-12-08 11:23 -0800
    Re: How to Create an XHR (Ajax) Object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-12-08 23:12 +0100
      Re: How to Create an XHR (Ajax) Object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-12-08 23:45 +0100
      Re: How to Create an XHR (Ajax) Object David Mark <dmark.cinsoft@gmail.com> - 2011-12-08 16:38 -0800
        Re: How to Create an XHR (Ajax) Object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-12-09 11:50 +0100
          Re: How to Create an XHR (Ajax) Object David Mark <dmark.cinsoft@gmail.com> - 2011-12-09 12:08 -0800
            Re: How to Create an XHR (Ajax) Object Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2011-12-10 20:56 +0100

csiph-web