Heim > Web-Frontend > js-Tutorial > Hauptteil

Schreiben leichter Ajax-Komponenten 02 – Eine kurze Analyse von AjaxPro

亚连
Freigeben: 2018-05-24 15:01:02
Original
1665 Leute haben es durchsucht

Obwohl Ajaxpro eine ältere Komponente ist, sind die Implementierungsideen und der Quellcode immer noch als Referenz wertvoll. Als nächstes werde ich Ihnen in diesem Artikel vorstellen, wie man leichte Ajax-Komponenten 02 schreibt – eine kurze Analyse von AjaxPro. Interessierte Freunde können sich auf das

Vorwort

beziehen Implementierung auf der Webform-Plattform. Einige Möglichkeiten von Ajax und der Implementierung einer Basisklasse. In diesem Artikel betrachten wir eine Open-Source-Komponente: ajaxpro. Obwohl es sich um eine ältere Komponente handelt, sind die Implementierungsideen und der Quellcode dennoch lernenswert. Durch die Einführung im vorherigen Artikel wissen wir, dass der Aufruf der Seitenobjektmethode durch Reflexion erreicht wird. Der Schlüssel liegt im gesamten Verarbeitungsprozess, einschließlich der Reflexionsaufrufmethode, der Parameterzuordnung usw. Ajaxpro hilft uns nicht nur bei der Implementierung dieses Prozesses im Hintergrund, sondern kapselt auch Anforderungsaufrufmethoden im Vordergrund, z. B. Ajax-bezogene Methoden. Sie können Ajaxpro-Methoden verwenden, um asynchrone Anforderungen zu senden, ohne js selbst zu kapseln oder eine js-Bibliothek zu verwenden. Als nächstes werden wir diese Komponente kurz analysieren.

1. Verwendung von Ajaxpro

Schauen wir uns zunächst an, wie diese Komponente verwendet wird.

 1. Registrieren Sie AjaxHandlerFactory

Nehmen Sie die folgende Konfiguration in web.config vor:

<httpHandlers>
 <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro"/>
</httpHandlers>
Nach dem Login kopieren

Einfach ausgedrückt entspricht die angeforderte URL ajaxpro/*. Das ashx-Format wird von AjaxHandlerFactory verarbeitet, einer Factory-Klasse, die die IHandlerFactory-Schnittstelle implementiert und zum Abrufen des IHandler-Handlers verwendet wird. Das Format des Typs ist: „Namenssteuerung. Klassenname, Assemblyname“.

 2. Registrieren Sie sich im Page_Load-Ereignis der Seitenklasse

protected void Page_Load(object sender, EventArgs e)
{
 AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxProPage));
}
Nach dem Login kopieren

Wir übergeben den Typ dieses Seitenobjekts an die ResisterTypoForAjax-Methode Skript im Vordergrund. Insbesondere wird der RegisterClientScriptBlock des aktuellen Seitenobjekts aufgerufen, daher muss ein

vorhanden sein, andernfalls wird das Skript nicht ausgeführt registriert werden. (Der Typ wird hier übergeben, aber es ist tatsächlich möglich, ihn zu übergeben. Dieser Typ kann auch intern über HttpContext.Current.Handler.GetType().BaseType abgerufen werden.)

 3 mit AjaxMethod 

[AjaxMethod]
public List<string> GetList(string input1,string input2)
{
 return new List<string> { input1, input2 };
}
Nach dem Login kopieren

AjaxMethod ist ein Tag-Attribut, das angibt, dass diese Methode zur Verarbeitung von Ajax-Anfragen verwendet wird und letztendlich über mehrere Konstruktorpaare ausgeführt wird. Für einige Daten ist dies erforderlich Wenn unsere Anfrage keine Sitzung verwenden muss, können wir HttpSessionStateRequirement festlegen. Wenn die Anfrage asynchron sein muss, z. B. um einen zeitaufwändigen Webdienst anzufordern, können wir den Handler auch auf festlegen asynchroner Zustand.

Der Rückgabewert einer Methode kann ein einfacher Typ oder ein komplexer Typ sein; der im Vordergrund erhaltene Sammlungstyp ist beispielsweise ein Array.

 4. Front-End-Aufruf

Die Konfiguration und Verwendung des Back-Ends ist sehr einfach. Sehen wir uns als Nächstes an, wie das Front-End eine Anfrage initiiert.

function GetList() {
 //var result = AjaxProNamespace.AjaxProPage.GetList("a", "b").value;
 //console.log(result);
 AjaxProNamespace.AjaxProPage.GetList("a", "b", function (result) {
  console.log(result);
 });  
}
Nach dem Login kopieren

Hier ist AjaxProNamespace der Namespace, in dem sich die Seitenklasse befindet, AjaxProPage ist der Name der Seitenklasse und GetList ist die markierte Methode. Warum kann es so geschrieben werden? Wie bereits erwähnt, registriert Ajaxpro das Skript im Vordergrund und generiert das folgende Skript basierend auf den relevanten Informationen unseres Seitenobjekts, sodass wir es so aufrufen können, ohne selbst js schreiben oder die jquery-Bibliotheksmethode verwenden zu müssen.

if(typeof AjaxProNamespace == "undefined") AjaxProNamespace={};
if(typeof AjaxProNamespace.AjaxProPage_class == "undefined") AjaxProNamespace.AjaxProPage_class={};
AjaxProNamespace.AjaxProPage_class = function() {};
Object.extend(AjaxProNamespace.AjaxProPage_class.prototype, Object.extend(new AjaxPro.AjaxClass(), {
 GetList: function(input1, input2) {
  return this.invoke("GetList", {"input1":input1, "input2":input2}, this.GetList.getArguments().slice(2));
 },
 url: &#39;/ajaxpro/AjaxProNamespace.AjaxProPage,TestAjaxProSourceCode.ashx&#39;
}));
AjaxProNamespace.AjaxProPage = new AjaxProNamespace.AjaxProPage_class();
Nach dem Login kopieren

 Die Parameter von GetList entsprechen den Parametern der Hintergrundmethode. Der Typ muss konvertierbar sein, sonst schlägt der Aufruf fehl. Der letzte Parameter ist die Rückruffunktion. Der Parameter der Rückruffunktion ist ein Objekt, das das Rückgabeergebnis kapselt. Der oben zurückgegebene Wert ist beispielsweise ein Array-Objekt. Der Fehler enthält Fehlerinformationen.

Beachten Sie, dass der auskommentierte Teil oben eine synchrone Anfrage ist, was oft nicht das ist, was wir wollen. Ich habe gesehen, dass jemand ihn falsch verwendet hat.

2. Prinzip der Ajaxpro-Verarbeitungsanfragen

Hier konzentrieren wir uns hauptsächlich auf den Prozess der Komponentenverarbeitung von Ajax-Anfragen, andere Hilfsfunktionen nicht eingeführt werden.

  1. Hilfsskript generieren

Im Page_Load-Ereignis haben wir AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxProPage)); aufgerufen, um das erforderliche Skript zu registrieren. Wir haben festgestellt, dass auf der Startseite das folgende Skript eingeführt wurde:

Das heißt, jede Seite initiiert diese Anfragen. Dies sind alles Dateien, die auf .ashx enden, aber eigentlich handelt es sich bei ihnen um JS-Code. Einige dieser JS sind als Ressourcen in der DLL verschachtelt, andere werden automatisch generiert. Sie kapseln hauptsächlich Ajax-Anforderungsmethoden und ermöglichen uns die Verwendung von: Namespace. Der Name der Seitenklasse wird zum Aufrufen der Methode verwendet. Warum .ashx statt .js verwenden? Denn als Ressourcendatei innerhalb der Komponente kann die .js-Datei nicht direkt von außen angefordert werden, sondern die .ashx kann abgefangen und der Inhalt dann mit Response.Write ausgegeben werden.

  如果每次都生成和发送这些脚本的效率是很低的,ajaxpro内部的处理是判断请求头的If-None-Math和If-Modified-Since,如果两个都和缓存的一样,就返回一个304状态码。所以,客户端只有首次请求服务端会返回文件的内容,后续的都只返回304表示使用本地缓存。我们刷新页面可以验证这个过程:

  2. 拦截请求

  HttpHandler(IHttpHandler) 和 HttpModule(IHttpModule) 是asp.net 两个重要的组件,让我们可以在asp.net的基础上很方便的进行扩展。HttpHandler对应某种具体的请求,例如.ashx,.aspx等;HttpModule是一个拦截器,可以在管道的某个事件对所有请求进行拦截。简单的说,在管道中,HttpApplication会触发一系列事件,我们在通过HttpModule对某个事件进行注册,例如我们可以在处理程序对象生成前拦截请求,然后映射到自己的处理程序;而实际处理请求返回结果的是HttpHandler,例如Page用来生成html。

  以asp.net mvc框架为例,它是建立在asp.net 路由机制的基础上的,asp.net 路由系统通过一个UrlRoutingModule对请求进行拦截,具体是在PostResolveRequestCache事件进行拦截,对url进行解析,封装相应的路由数据后,最终将请求交给一个MvcHandler进行处理,MvcHandler实现了IHttpHandler接口。

  前面我们进行了如下配置: 这表明了任何的以 ajaxpro/任意名称.ashx结尾的 Post/Get 请求,都交给AjaxPro.AjaxHandlerFactory进行处理,它是一个实现了IHandlerFactory的处理程序工厂,用来生成具体的IHttpHandler。组件内部定义了多个实现IHttpHandler的类,有的是为了生成js脚本的,对于处理ajax请求,主要分为两类:异步(IHttpAsyncHandler)和非异步(IHttpHandler);在这两类的基础上,对于Session的状态的支持又分为三种:支持读写(实现IRequiresSessionState标记接口)的Handler、只读(实现IReadOnlySessionState标记接口)的Handler和不支持Session的Handler。具体生成什么样的Handler是通过AjaxMethod进行判断的。

  IHttpHandler的ProcessRequest(异步就是BeginProcessRequest)就用来执行请求返回输出结果的。如果只需要一种处理程序我们也可以实现IHttpHandler。IHandlerFactory的定义如下:

public interface IHttpHandlerFactory
{
 IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated);
 void ReleaseHandler(IHttpHandler handler);
} 
Nach dem Login kopieren

  所以,ajaxpro的所有请求都会符合ajaxpro/*.ashx格式,然后在GetHandler方法,就可以进行具体的处理,返回结果是IHttpHandler;以非异步状态为例,如果我们配置了需要Session,就会生成一个实现IHttpHandler和IRequiresSessionState的Handler,如果需要只读的Session,就会生成一个实现IHttpHandler和IReadOnlySessionState的Handler;这些信息可以通过反射从AjaxMethod标记属性获得。AjaxHandlerFactory的主要代码如下:

public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
 string filename = Path.GetFileNameWithoutExtension(context.Request.Path);
 Type t = null;
 Exception typeException = null;
 bool isInTypesList = false;
 switch (requestType)
 {
  //Get请求,获取前面的那4个脚本
  case "GET": 
   switch (filename.ToLower())
   {
    case "prototype":
     return new EmbeddedJavaScriptHandler("prototype");
    case "core":
     return new EmbeddedJavaScriptHandler("core");
    case "ms":
     return new EmbeddedJavaScriptHandler("ms");
    case "prototype-core":
    case "core-prototype":
     return new EmbeddedJavaScriptHandler("prototype,core");
    case "converter":
     return new ConverterJavaScriptHandler();
    default:
     return new TypeJavaScriptHandler(t);
   }
  case "POST":
   IAjaxProcessor[] p = new IAjaxProcessor[2];
   p[0] = new XmlHttpRequestProcessor(context, t);
   p[1] = new IFrameProcessor(context, t);
   for (int i = 0; i < p.Length; i++)
   {
    if (p[i].CanHandleRequest)
    {
     //获取标记方法的AjaxMethod属性
     AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])p[i].AjaxMethod.GetCustomAttributes(typeof(AjaxMethodAttribute), true);
     bool useAsync = false;
     HttpSessionStateRequirement sessionReq = HttpSessionStateRequirement.ReadWrite;
     if (ma.Length > 0)
     {
      useAsync = ma[0].UseAsyncProcessing;
      if (ma[0].RequireSessionState != HttpSessionStateRequirement.UseDefault)
       sessionReq = ma[0].RequireSessionState;
     }
     //6种Handler,根据是否异步,session状态返回指定的Handler
     switch (sessionReq)
     {
      case HttpSessionStateRequirement.Read:
       if (!useAsync)
        return new AjaxSyncHttpHandlerSessionReadOnly(p[i]);
       else
        return new AjaxAsyncHttpHandlerSessionReadOnly(p[i]);
      case HttpSessionStateRequirement.ReadWrite:
       if (!useAsync)
        return new AjaxSyncHttpHandlerSession(p[i]);
       else
        return new AjaxAsyncHttpHandlerSession(p[i]);
      case HttpSessionStateRequirement.None:
       if (!useAsync)
        return new AjaxSyncHttpHandler(p[i]);
       else
        return new AjaxAsyncHttpHandler(p[i]);
      default:
       if (!useAsync)
        return new AjaxSyncHttpHandlerSession(p[i]);
       else
        return new AjaxAsyncHttpHandlerSession(p[i]);
     }
    }
   }
   break;
 }
 return null;
}
Nach dem Login kopieren

  3. 反射执行方法

  当获得一个处理本次请求的Handler后,就可以在其ProcessRequest(异步为BeginProcessRequest)执行指定的方法。要执行一个页面对象的方法,我们必须知道指定页面所在的程序集,名称空间,页面类的名称以及方法的名称。这似乎符合我们前面:名称空间.类名称.方法名称的调用方式。为了与一般请求区分开,让组件具有足够的独立性,ajaxpro只拦截符合"ajaxpro/*.ashx格式的请求,这说明我们的ajax请求也要符合这个格式。如:http://localhost:50712/ajaxpro/AjaxProNamespace.AjaxProPage,TestAjaxProSourceCode.ashx,这个格式由前台脚本自动生成,并不需要我们去构造。仔细观察,会发现AjaxProNamespace.AjaxProPage,TestAjaxProSourceCode 就是页面类的完全限定名:名称空间.类名称,程序集名称,通过这个我们就可以生成具体的Type,然后进行反射获取信息。那么方法的名称呢?ajaxpro将其放在http header 中,名称为:X-AjaxPro-Method。有了这些信息,就可以反射执行方法了。这里核心代码为:

internal void Run()
{
 try
 {
  //设置输出结果不缓存(这不一定是我们想要的)
  p.Context.Response.Expires = 0;
  p.Context.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
  p.Context.Response.ContentType = p.ContentType;
  p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8;
  //验证ajax请求
  if (!p.IsValidAjaxToken())
  {
   p.SerializeObject(new System.Security.SecurityException("The AjaxPro-Token is not valid."));
   return;
  }
  //方法参数对象数组
  object[] po = null;
  //请求处理结果
  object res = null;
  try
  {
   //获取参数
   po = p.RetreiveParameters();
  }
  catch (Exception ex){}
  //获取缓存的Key
  string cacheKey = p.Type.FullName + "|" + p.GetType().Name + "|" + p.AjaxMethod.Name + "|" + p.GetHashCode();
  if (p.Context.Cache[cacheKey] != null)
  {
   //如果缓存存在,则直接使用缓存
   p.Context.Response.AddHeader("X-" + Constant.AjaxID + "-Cache", "server");
   p.Context.Response.Write(p.Context.Cache[cacheKey]);
   return;
  }
  try
  {
   if (p.AjaxMethod.IsStatic)
   {
    //使用反射调用静态方法
    try
    {
     res = p.Type.InvokeMember(
      p.AjaxMethod.Name,
      System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod,
      null, null, po);
    }
    catch (Exception ex){}
   }
   else
   {
    try
    {
     //创建实例对象,反射调用实例方法
     object c = (object)Activator.CreateInstance(p.Type, new object[] { });
     if (c != null)
     {
      res = p.AjaxMethod.Invoke(c, po);
     }
    }
    catch (Exception ex){}
   }
  }
  catch (Exception ex){}
  try
  {
   //判断结果是不是xml,如是设置ContentType
   if (res != null && res.GetType() == typeof(System.Xml.XmlDocument))
   {
    p.Context.Response.ContentType = "text/xml";
    p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8;
    ((System.Xml.XmlDocument)res).Save(p.Context.Response.OutputStream);
    return;
   }
   string result = null; ;
   System.Text.StringBuilder sb = new System.Text.StringBuilder();
   try
   {
    result = p.SerializeObject(res);
   }
   catch (Exception ex){}
   //如果需要缓存,则将结果写入缓存
   if (p.ServerCacheAttributes.Length > 0)
   {
    if (p.ServerCacheAttributes[0].IsCacheEnabled)
    {
     p.Context.Cache.Add(cacheKey, result, null, DateTime.Now.Add(p.ServerCacheAttributes[0].CacheDuration), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
    }
   }
  }
  catch (Exception ex){}
 }
 catch (Exception ex){}
}
Nach dem Login kopieren

三、总结

  我们总结一下ajaxpro的核心处理流程,它通过一个IHttpHandlerFactory拦截指定格式的url,然后从中获取类型的完全限定名生成类型对象,接着通过反射获取标记方法的特性,生成一个自定义的实现IHttpHandler接口的对象;在其ProcessRequest方法中,从http headers获取方法名称,通过反射进行参数映射并执行函数。

 ajaxpro bietet folgende Vorteile:

 1. Einfache Konfiguration.

 2. Kann in Verbindung mit anderen Komponenten verwendet werden.

 3. Kapseln Sie das Front-End-Skript. Wir müssen es nicht selbst kapseln oder andere Skriptbibliotheken verwenden.

 4. Für die Rückgabewertverarbeitung können wir einfache Typen oder komplexe Typen zurückgeben, die automatisch serialisiert werden. ​

 Die Nachteile sind:

 1. Die Seite wird 4 weitere Anfragen haben. Obwohl 304-Caching verwendet wird, muss dennoch eine Anfrage an den Server gesendet werden.

 2. Ajax kann die Get-Anfrage nicht verwenden. Da das URL-Format angepasst ist, können Get-Anfragen nicht mit diesem Format verwendet werden. Wir wissen, dass Get-Anfragen von Browsern zwischengespeichert werden können. Einer der Front-End-Optimierungsvorschläge von Yahoo besteht darin, mehr Get-Anfragen zu verwenden. Tatsächlich sollten wir den Namespace, den Klassennamen und die Assembly in den HTTP-Header einfügen und dann einen Typparameter bereitstellen, den wir frei wählen können.

3. Binden Sie mit

. Der Zweck besteht darin, ein Front-End-Skript für uns zu generieren. Wenn wir jedoch die Methode .html-Datei + .aspx.cs verwenden möchten, kann sie nicht verwendet werden (einige Seiten im Blog-Park verwenden diese Methode möglicherweise). müssen verschoben werden. Bei der End-to-End-Nutzung wird dieser Komfort zu einer Einschränkung.

 4. Reflexion. Dies ist relativ ineffizient und speichert MethodInfo nicht einmal zwischen, wie unsere vorherige Seitenklasse.

Es zeigt sich, dass sich der Einsatz dieser Komponente auch dann lohnt, wenn Ihnen die Effizienz egal ist. Hier ist nur eine Kerneinführung, es gibt viele andere Funktionen. Dies ist der Quellcode der Ajaxpro-Komponente. Interessierte Freunde können ihn studieren.

Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.

Verwandte Artikel:

Eine kurze Analyse des Unterschieds zwischen JSON und JSONP und der Formatkonvertierung nach Erhalt von JSON-Daten über Ajax

Das Django-Framework verwendet Ajax. Implementieren Sie die Batch-Importdatenfunktion.

Detaillierte Erläuterung des AJAX XMLHttpRequest-Objekts

Das obige ist der detaillierte Inhalt vonSchreiben leichter Ajax-Komponenten 02 – Eine kurze Analyse von AjaxPro. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage