admin管理员组文章数量:1569582
Ajax是目前web开发中使用很基本的技术了,搞web的程序员一定都搞过Ajax,即使没有自己用javascript写过原生Ajax,也一定使用过javascript框架中封装好的Ajax,比如jquery中,就有对Ajax的很好封装。
不过,用过,不见得就对Ajax真的了解的透彻,比如,Ajax技术是如何实现的?使用Ajax的时候,javascript扮演的角色是什么?浏览器时候是如何工作的?外部数据又是怎样返回到你调用的javascipt程序内?…诸如此类的问题,还是有很多开发人员没有想过,即使想过,也没有深入了解过这个问题。
没关系,下面我将对Ajax的实现做一次透彻的分析。
我以下所讲内容,全部基于webkit内核浏览器,所以有些内容可能不适用于Trident,Gecko或者其他内核
要弄透彻Ajax的工作方式,就要首先了解一下什么是Ajax
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。
从描述上可以看出,Ajax并非一种javascript的方法。而是javascript的一个应用方式
。所以基于上述分析,及应该可以了解到,Ajax并非依靠javascript代码就能实现,它必须依靠浏览器更底层工作才能实现,然后作为一个应用,由javascript调用,从而实现后台运行获取数据,而不用通过刷新页面获取数据
下面是一段标准的javascript实现Ajax的过程
var xmlhttp;
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
xmlhttp.responseText;
}
}
xmlhttp.open("GET","http://www.google",true);
xmlhttp.send();
下面通过上面这个一段简单的脚本来说明Ajax的具体工作方式
1.JavaScript的角色
脚本很简单,不用多解释,先说明一点,关于XMLHttpRequest的所有属性方法都定义webkit源码的JSXMLHttpRequest.cpp中。
在webkit中,javascript是通过javascriptcore(javascript引擎)实现的,javascriptcore是很好的JS引擎,自带JIT。具体可查看webkit源码,Source\JavaScriptCore文件夹下便是全部的jsc的实现代码。
webkit通过桥接程序,将javascriptcore API与dom 经行连接,让javascript可以操作htmldom,具体可见Source\WebCore\bridge
以上是一些基本的webkit知识,现在看我们上面写的代码,第一句不用看,谁都知道啥意思.
现在主要看第二句
new XMLHttpRequest,
XMLHttpRequest方法定义在Source\WebCore\xml\XMLHttpRequest.cpp
这个是创建一个XMLHttpRequest对象
XMLHttpRequest::XMLHttpRequest(ScriptExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin):ActiveDOMObject(context, this)
当你调用onreadystatechange实际是调用了
setJSXMLHttpRequestOnreadystatechange
void setJSXMLHttpRequestOnreadystatechange(ExecState* exec, JSObject* thisObject, JSValue value)
{
UNUSED_PARAM(exec);
JSXMLHttpRequest* castedThis = static_cast<JSXMLHttpRequest*>(thisObject);
XMLHttpRequest* impl = static_cast<XMLHttpRequest*>(castedThis->impl());
impl->setOnreadystatechange(createJSAttributeEventListener(exec, value, thisObject));
}
impl->setOnreadystatechange(createJSAttributeEventListener(exec, value, thisObject))
这句话至关重要,这个就是你定义的无名函数,在数据返回时,程序将调用你刚才定义的代码,接下来
xmlhttp.open(“GET”,”www.google",true);
这句话会调用Source\WebCore\bindings\js\JSXMLHttpRequestCustom.cpp,目的是通过参数进行调用不同的函数重载,有一些参数,比如user,async这些都是判断时候同步,是否有用户名,密码KURL是webkit处理url时的统一类,主要记录url地址jsUndefined() 是每一个jsc函数扩展的返回类型,如果没有js返回,则返回jsUndefined(),就是js代码中的undefied;
JSValue JSXMLHttpRequest::open(ExecState* exec)
{
if (exec->argumentCount() < 2)
return throwError(exec, createSyntaxError(exec, "Not enough arguments"));
const KURL& url = impl()->scriptExecutionContext()->completeURL(ustringToString(exec->argument(1).toString(exec)->value(exec)));
String method = ustringToString(exec->argument(0).toString(exec)->value(exec));
ExceptionCode ec = 0;
if (exec->argumentCount() >= 3) {
bool async = exec->argument(2).toBoolean(exec);
if (exec->argumentCount() >= 4 && !exec->argument(3).isUndefined()) {
String user = valueToStringWithNullCheck(exec, exec->argument(3));
if (exec->argumentCount() >= 5 && !exec->argument(4).isUndefined()) {
String password = valueToStringWithNullCheck(exec, exec->argument(4));
impl()->open(method, url, async, user, password, ec);
} else
impl()->open(method, url, async, user, ec);
} else
impl()->open(method, url, async, ec);
} else
impl()->open(method, url, ec);
setDOMException(exec, ec);
return jsUndefined();
}
以上全是为要发起请求所做的工作,执行xmlhttp.send()才会真正的发送请求,一直到createRequest(ec)以前,还是为发起请求做一个必要的需求,比如判断发送方式、定义httphead、设置字符集。createRequest(ec)是真的开始请求了
void XMLHttpRequest::send(const String& body, ExceptionCode& ec)
{
if (!initSend(ec))
return;
if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && m_url.protocolInHTTPFamily()) {
String contentType = getRequestHeader("Content-Type");
if (contentType.isEmpty()) {
#if ENABLE(DASHBOARD_SUPPORT)
if (usesDashboardBackwardCompatibilityMode())
setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");
else
#endif
setRequestHeaderInternal("Content-Type", "application/xml");
} else {
replaceCharsetInMediaType(contentType, "UTF-8");
m_requestHeaders.set("Content-Type", contentType);
}
m_requestEntityBody = FormData::create(UTF8Encoding().encode(body.characters(), body.length(), EntitiesForUnencodables));
if (m_upload)
m_requestEntityBody->setAlwaysStream(true);
}
createRequest(ec);
}
当然,webkit代码中通过了好多层调用才到了我们上面看的代码,并不是仅仅只有上面一点,不过上面就是代码就是JS操作的基本方式,在javascript代码中,他能做的就是以上这些工作
总结一下,javascript在ajax是所做的工作
有了以上的工作,javascript端就是完成了,具体是如何开是调用数据的,又如何使用异步调用的,请看一下节
本文同步发布于http://www.ltplayer/blog/2018/12/24/ajax1/
版权声明:本文标题:Ajax在浏览器上具体是如何执行的(1) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1725798937a1043329.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论