AOP Techniques for Ajax and Jsonp in Front-End Development

The article explains how to use Aspect‑Oriented Programming to globally intercept and rewrite Ajax and JSONP requests—both native and framework based—by extending Function.prototype, overriding DOM methods, and employing ajax‑hook and Axios interceptors, culminating in a runnable demo that redirects traffic from a‑domain to b‑domain.

37 Interactive Technology Team
37 Interactive Technology Team
37 Interactive Technology Team
AOP Techniques for Ajax and Jsonp in Front-End Development

Technical background : In early 2022 a project to separate secondary business interfaces was launched. The original architecture had domain A providing both activity‑type APIs and SDK‑type APIs, with SDK traffic accounting for 98% of the load, creating a strong performance optimisation need. The goal was to split the A‑domain interfaces and provide a generic, convenient solution, which led to the adoption of Aspect‑Oriented Programming (AOP).

Review of native and framework Ajax/Jsonp implementations : The article first revisits two native implementations – a plain XMLHttpRequest based Ajax function and a script‑tag based Jsonp function – and then shows how popular frameworks (jQuery and Axios) wrap these functionalities.

function myAjax(url) {
  const events = ['load','loadend','timeout','error','readystatechange','abort'];
  const xhr = new XMLHttpRequest();
  xhr.open('get', url, true);
  xhr.send();
  events.forEach(function(e){
    xhr['on' + e] = function(event){ console.log('on' + e, xhr.readyState, event); };
    xhr.addEventListener(e,function(event){ console.log(e, xhr.readyState, event); });
  });
  xhr.addEventListener('load',function(event){ console.log('response', xhr.response); });
}

function myJsonp(params){
  params = params || {};
  params.data = params.data || {};
  const callbackName = params.jsonp;
  const head = document.querySelector('head');
  const script = document.createElement('script');
  params.data['callback'] = callbackName;
  const formateData = data => {
    let arr = [];
    for(let key in data){ arr.push(encodeURIComponent(key) + '=' + data[key]); }
    return arr.join('&');
  };
  const data = formateData(params.data);
  script.src = `${params.url}?${data}`;
  window[callbackName] = function(jsonData){
    head.removeChild(script);
    clearTimeout(script.timer);
    window[callbackName] = null;
    params.success && params.success(jsonData);
  };
  if(params.time){
    script.timer = setTimeout(()=>{
      window[callbackName] = null;
      head.removeChild(script);
      params.error && params.error({message:'超时'});
    }, params.time);
  }
  head.appendChild(script);
}

Framework examples include jQuery's $.ajax, $.get, $.post and Axios interceptors for request/response handling.

axios.interceptors.request.use(function (config) {
  // Do something before request is sent
  return config;
}, function (error) {
  return Promise.reject(error);
});

axios.interceptors.response.use(function (response) {
  // Do something with response data
  return response;
}, function (error) {
  return Promise.reject(error);
});

Quick AOP overview : AOP (Aspect‑Oriented Programming) introduces three core concepts – joint‑point (the original method), advice (the interception timing) and point‑cut (the method to be intercepted). In JavaScript these can be implemented by extending Function.prototype with before and after helpers.

Function.prototype.before = function (func) {
  const __self = this;
  return function(){
    if (func.apply(this, arguments) === false) return false;
    return __self.apply(this, arguments);
  };
};

Function.prototype.after = function (func) {
  const __self = this;
  return function(){
    const ret = __self.apply(this, arguments);
    if (ret === false) return false;
    func.apply(this, arguments);
    return ret;
  };
};

Using these helpers, the article demonstrates how to rewrite Node.prototype.appendChild and Node.prototype.insertBefore to intercept Jsonp script insertion, achieving a universal AOP solution for both native and jQuery Jsonp calls.

function jsonpReqUrlRewrite(thisEle){
  const isHTMLScriptElement = Object.prototype.toString.call(thisEle) === '[object HTMLScriptElement]';
  if (!isHTMLScriptElement) return false;
  const pathMap = ['/activity/execute','/api/','/ajax/'];
  for (const path of pathMap){
    if (thisEle.src.includes(path)){
      thisEle.src = thisEle.src.replace(/a-domain/, 'b-domain');
      break;
    }
  }
}

Node.prototype.appendChild = Node.prototype.appendChild.before(jsonpReqUrlRewrite);
Node.prototype.insertBefore = Node.prototype.insertBefore.before(jsonpReqUrlRewrite);

For Ajax, the article uses ajax‑hook to globally intercept all Ajax/Jsonp requests, rewriting URLs based on a path map before the request is sent.

ah.proxy({
  onRequest: (config, handler) => {
    const pathMap = ['/activity/execute','/api/','/ajax/'];
    for (const path of pathMap){
      if (config.url.includes(path)){
        config.url = config.url.replace(/a-domain/, 'b-domain');
        break;
      }
    }
    handler.next(config);
  },
  onError: (err, handler) => { handler.next(err); },
  onResponse: (response, handler) => { handler.next(response); }
});

The final part of the article provides a complete HTML demo that ties together the native Ajax/Jsonp functions, the ajax‑hook AOP, the Axios interceptor example, and the Jsonp AOP via appendChild / insertBefore overrides. Buttons in the demo trigger native Ajax, jQuery Ajax, native Jsonp, and jQuery Jsonp requests, all of which are automatically rewritten from the a-domain to b-domain thanks to the AOP layers.

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
  <meta charset="UTF-8">
  <title>Ajax & Jsonp AOP</title>
  <script src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/ajaxhook.min.js"></script>
</head>
<body>
  <button id="native-ajax-btn">native-ajax-btn</button>
  <button id="jquery-ajax-btn">jquery-ajax-btn</button>
  <button id="native-jsonp-btn">native-jsonp-btn</button>
  <button id="jquery-jsonp-btn">jquery-jsonp-btn</button>
  <script>
    // (All the functions and AOP code shown above are placed here)
    $('#native-ajax-btn').click(function(){ myAjax('https://a-domain.37games.com/activity/execute'); });
    $('#jquery-ajax-btn').click(function(){ $.post('https://a-domain.37games.com/activity/execute',{name:'christmas2021',action:'check_time'}).done(function(r){ alert(r.msg); }); });
    $('#native-jsonp-btn').click(function(){ myJsonp({url:'https://a-domain.37games.com/activity/execute',jsonp:'callback',data:{name:'christmas2021',action:'check_time'},success:function(r){ console.log('jsonp success:',r); }}); });
    $('#jquery-jsonp-btn').click(function(){ $.ajax({url:'https://a-domain.37games.com/activity/execute',data:{name:'christmas2021',action:'check_time'},jsonp:'callback',dataType:'jsonp',success:function(r){ alert(r.msg); }}); });
  </script>
</body>
</html>

In summary, the article demonstrates three key takeaways:

Using ajax‑hook to apply AOP to all Ajax/Jsonp usage scenarios.

Overriding appendChild and insertBefore to achieve AOP for Jsonp across any front‑end stack.

Providing a ready‑to‑run demo that showcases the complete workflow.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptaopaxiosHookajaxJSONP
37 Interactive Technology Team
Written by

37 Interactive Technology Team

37 Interactive Technology Center

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.