参考博客:http://www.cnblogs.com/xiaohuochai/p/6543019.html

http://www.cnblogs.com/qcloud1001/p/6839541.html

使用CORS 实现Ajax的另类跨域:关于浏览器端,以jQuery为例,我们需要在ajax请求中加一个参数xhrFields,并设置为withCredentials : true。

www.cnblogs.com/Darren_code…

/** * 防止浏览器缓存页面或请求结果 * @author XuJijun * */  
public class NoCacheFilter implements Filter {  @Override  public void destroy(){  }  @Override  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {  HttpServletResponse response = (HttpServletResponse)resp;  response.setDateHeader("Expires", -1);  response.setHeader("Cache_Control", "no-cache");  response.setHeader("Pragma", "no-cache");  response.setHeader("Access-Control-Allow-Origin", "*");     //允许跨域请求  chain.doFilter(req, resp);  }  @Override  public void init(FilterConfig arg0) throws ServletException {  }  
}  
复制代码


默认情况下,跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等)。通过将withCredentials属性设置为true,可以指定某个请求应该发送凭据。如果服务器接收带凭据的请求,会用下面的HTTP头部来响应。

其实就是我们刚才设置的第二条配置。

虽然设置了widthCredentials为true的请求中会包含远程域的所有cookie,但这些cookie仍然遵循同源策略,所以外域是访问不了这些cookie的,现在我们就可以安全地跨域访问啦。




www.cnblogs.com/xiaohuochai…

一、input:file属性
属性值有以下几个比较常用:
accept:表示可以选择的文件MIME类型,多个MIME类型用英文逗号分开,常用的MIME类型见下表。
multiple:是否可以选择多个文件,多个文件时其value值为第一个文件的虚拟路径。
1、accept
只能选择png和gif图片
<input id="fileId1" type="file" accept="image/png,image/gif" name="file" />
2、multiple
多文件上传
<input id="fileId2" type="file" multiple="multiple" name="file" />
3、常用MIME类型
后缀名       MIME名称
*.3gpp    audio/3gpp, video/3gpp
*.ac3    audio/ac3
*.asf       allpication/vnd.ms-asf
*.au           audio/basic
*.css           text/css
*.csv           text/csv
*.doc    application/msword    
*.dot    application/msword    
*.dtd    application/xml-dtd    
*.dwg    image/vnd.dwg    
*.dxf      image/vnd.dxf
*.gif            image/gif    
*.htm    text/html    
*.html    text/html    
*.jp2            image/jp2    
*.jpe       image/jpeg
*.jpeg    image/jpeg
*.jpg          image/jpeg    
*.js       text/javascript, application/javascript    
*.json    application/json    
*.mp2    audio/mpeg, video/mpeg    
*.mp3    audio/mpeg    
*.mp4    audio/mp4, video/mp4    
*.mpeg    video/mpeg    
*.mpg    video/mpeg    
*.mpp    application/vnd.ms-project    
*.ogg    application/ogg, audio/ogg    
*.pdf    application/pdf    
*.png    image/png    
*.pot    application/vnd.ms-powerpoint    
*.pps    application/vnd.ms-powerpoint    
*.ppt    application/vnd.ms-powerpoint    
*.rtf            application/rtf, text/rtf    
*.svf           image/vnd.svf    
*.tif         image/tiff    
*.tiff       image/tiff    
*.txt           text/plain    
*.wdb    application/vnd.ms-works    
*.wps    application/vnd.ms-works    
*.xhtml    application/xhtml+xml    
*.xlc      application/vnd.ms-excel    
*.xlm    application/vnd.ms-excel    
*.xls           application/vnd.ms-excel    
*.xlt      application/vnd.ms-excel    
*.xlw      application/vnd.ms-excel    
*.xml    text/xml, application/xml    
*.zip            aplication/zip    
*.xlsx     application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
二、样式美化
请看博客:css input[type=file] 样式美化,input上传按钮美化 http://www.haorooms.com/post/css_input_uploadmh
三、AJAX上传文件
在说到ajax上传文件,之前的文章也有说过(详见:JS学习32:html5拖拽图片批量ajax无刷新进度上传)。ajax上传的时候,需要获得input:file选择的文件(可能为多个文件),获取其文件列表为:
// input标签的files属性
document.querySelector("#fileId").files
// 返回的是一个文件列表数组
获得的文件列表,然后遍历插入到表单数据当中。即:
// 获得上传文件DOM对象
var oFiles = document.querySelector("#fileId");// 实例化一个表单数据对象
var formData = new FormData();// 遍历图片文件列表,插入到表单数据中
for (var i = 0, file; file = oFiles[i]; i++) {// 文件名称,文件对象formData.append(file.name, file);
}
获得表单数据之后,就可以用ajax的POST上传。
// 实例化一个AJAX对象
var xhr = new XMLHttpRequest();
xhr.onload = function() {alert("上传成功!");
}
xhr.open("POST", "upload.php", true);// 发送表单数据
xhr.send(formData);
上传到服务器之后,获取到文件列表为:
Array
([jpg_jpg] => Array([name] => jpg.jpg[type] => image/jpeg[tmp_name] => D:\xampp\tmp\phpA595.tmp[error] => 0[size] => 133363)[png_png] => Array([name] => png.png[type] => image/png[tmp_name] => D:\xampp\tmp\phpA5A6.tmp[error] => 0[size] => 1214628))
在服务端循环遍历这个数组就可以上传文件了。
复制代码
<input id="postfile" type="file" accept="text/plain" multiple="multiple" />
复制代码
		function postFile() { //判断是否有选择上传文件var imgPath = $("#postfile").val();if(imgPath == "") {$(".poststate").text("请选择上传的文本文件,以.txt后缀结尾!").css("color", "blue");return;}var strExtension = imgPath.substr(imgPath.lastIndexOf('.') + 1); //判断上传文件的后缀名if(strExtension != 'txt') {$(".poststate").text("请选择上传的文本文件,以.txt后缀结尾!").css("color", "blue");return;}var formData = new FormData();formData.append("file", $("#postfile")[0].files[0]);console.log(postfile.files[0]);$.ajax({contentType: "multipart/form-data",url: "s3/operationmsg/upload",type: "POST",data: formData,dataType: "text",processData: false,contentType: false,cache: false,beforeSend: function() {$(".poststate").text("正在努力上传中,请稍后!").css("color", "green");},success: function(data) {var reObj = JSON.parse(data);if(reObj.content) {$(".poststate").text('"' + reObj.content.fileName + '"' + "上传成功!").css("color", "green");}},error: function(XMLHttpRequest, textStatus, errorThrown) {$(".poststate").text("上传失败,请检查网络后重试!").css("color", "red");;}});}$("#postfile").on('change', function() { //文件上传$(".poststate").text("请选择上传以.txt后缀结尾的文本文件!").css("color", "blue");postFile();});
复制代码



var fileInfo =$('#inputfile').prop('files')[0];var fd = new FormData();fd.append("xxxx", fileInfo);$.ajax({url: "xxxx.htm",type: "POST",processData: false, contentType: false, dataType: 'json', data: fd, success:function(data){},error:function(data){}});
复制代码



Ajax 知识体系大梳理

这是一篇万字长文, 系统梳理了ajax相关的知识体系, 几乎囊括了所有ajax的知识点.

原文: louiszhai.github.io/2016/11/02/…

导读

Ajax 全称 Asynchronous JavaScript and XML, 即异步JS与XML. 它最早在IE5中被使用, 然后由Mozilla, Apple, Google推广开来. 典型的代表应用有 Outlook Web Access, 以及 GMail. 现代网页中几乎无ajax不欢. 前后端分离也正是建立在ajax异步通信的基础之上.

浏览器为ajax做了什么

现代浏览器中, 虽然几乎全部支持ajax, 但它们的技术方案却分为两种:

① 标准浏览器通过 XMLHttpRequest 对象实现了ajax的功能. 只需要通过一行语句便可创建一个用于发送ajax请求的对象.

var xhr = new XMLHttpRequest();复制代码

② IE浏览器通过 XMLHttpRequest 或者 ActiveXObject 对象同样实现了ajax的功能.

MSXML

鉴于IE系列各种 "神级" 表现, 我们先来看看IE浏览器风骚的走位.

IE下的使用环境略显复杂, IE7及更高版本浏览器可以直接使用BOM的 XMLHttpRequest 对象. MSDN传送门: Native XMLHTTPRequest object. IE6及更低版本浏览器只能使用 ActiveXObject对象来创建 XMLHttpRequest 对象实例. 创建时需要指明一个类似"Microsoft.XMLHTTP"这样的ProgID. 而实际呢, windows系统环境下, 以下ProgID都应该可以创建XMLHTTP对象:

Microsoft.XMLHTTP
Microsoft.XMLHTTP.1.0
Msxml2.ServerXMLHTTP
Msxml2.ServerXMLHTTP.3.0
Msxml2.ServerXMLHTTP.4.0
Msxml2.ServerXMLHTTP.5.0
Msxml2.ServerXMLHTTP.6.0
Msxml2.XMLHTTP
Msxml2.XMLHTTP.3.0
Msxml2.XMLHTTP.4.0
Msxml2.XMLHTTP.5.0
Msxml2.XMLHTTP.6.0复制代码

简言之, Microsoft.XMLHTTP 已经非常老了, 主要用于提供对历史遗留版本的支持, 不建议使用.对于 MSXML4, 它已被 MSXML6 替代; 而 MSXML5 又是专门针对office办公场景, 在没有安装 Microsoft Office 2003 及更高版本办公软件的情况下, MSXML5 未必可用. 相比之下, MSXML6 具有比 MSXML3 更稳定, 更高性能, 更安全的优势, 同时它也提供了一些 MSXML3 中没有的功能, 比如说 XSD schema. 唯一遗憾的是, MSXML6 只在 vista 系统及以上才是默认支持的; 而 MSXML3 在 Win2k SP4及以上系统就是可用的. 因此一般情况下, MSXML3 可以作为 MSXML6 的优雅降级方案, 我们通过指定 PorgID 为 Msxml2.XMLHTTP 即可自动映射到 Msxml2.XMLHTTP.3.0. 如下所示:

var xhr = new ActiveXObject("Msxml2.XMLHTTP");// 即MSXML3,等同于如下语句
var xhr = new ActiveXObject("MSXML2.XMLHTTP.3.0");复制代码

MSDN有篇文章专门讲解了各个版本的MSXML. 传送门: Using the right version of MSXML in Internet Explorer.

亲测了 IE5, IE5.5, IE6, IE7, IE8, IE9, IE10, IE edge等浏览器, IE5及之后的浏览器均可以通过如下语句获取xhr对象:

var xhr = new ActiveXObject("Msxml2.XMLHTTP");// 即MSXML3
var xhr = new ActiveXObject("Microsoft.XMLHTTP");// 很老的api,虽然浏览器支持,功能可能不完善,故不建议使用复制代码

以上, 思路已经很清晰了, 下面给出个全兼容的方法.

全平台兼容的XMLHttpRequest对象

function getXHR(){var xhr = null;if(window.XMLHttpRequest) {xhr = new XMLHttpRequest();} else if (window.ActiveXObject) {try {xhr = new ActiveXObject("Msxml2.XMLHTTP");} catch (e) {try {xhr = new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { alert("您的浏览器暂不支持Ajax!");}}}return xhr;
}复制代码

ajax有没有破坏js单线程机制

对于这个问题, 我们先看下浏览器线程机制. 一般情况下, 浏览器有如下四种线程:

  • GUI渲染线程
  • javascript引擎线程
  • 浏览器事件触发线程
  • HTTP请求线程

那么这么多线程, 它们究竟是怎么同js引擎线程交互的呢?

通常, 它们的线程间交互以事件的方式发生, 通过事件回调的方式予以通知. 而事件回调, 又是以先进先出的方式添加到任务队列 的末尾 , 等到js引擎空闲时, 任务队列 中排队的任务将会依次被执行. 这些事件回调包括 setTimeout, setInterval, click, ajax异步请求等回调.

浏览器中, js引擎线程会循环从 任务队列 中读取事件并且执行, 这种运行机制称作 Event Loop(事件循环).

对于一个ajax请求, js引擎首先生成 XMLHttpRequest 实例对象, open过后再调用send方法. 至此, 所有的语句都是同步执行. 但从send方法内部开始, 浏览器为将要发生的网络请求创建了新的http请求线程, 这个线程独立于js引擎线程, 于是网络请求异步被发送出去了. 另一方面, js引擎并不会等待 ajax 发起的http请求收到结果, 而是直接顺序往下执行.

当ajax请求被服务器响应并且收到response后, 浏览器事件触发线程捕获到了ajax的回调事件 onreadystatechange (当然也可能触发onload, 或者 onerror等等) . 该回调事件并没有被立即执行, 而是被添加到 任务队列 的末尾. 直到js引擎空闲了, 任务队列 的任务才被捞出来, 按照添加顺序, 挨个执行, 当然也包括刚刚append到队列末尾的 onreadystatechange 事件.

onreadystatechange 事件内部, 有可能对dom进行操作. 此时浏览器便会挂起js引擎线程, 转而执行GUI渲染线程, 进行UI重绘(repaint)或者回流(reflow). 当js引擎重新执行时, GUI渲染线程又会被挂起, GUI更新将被保存起来, 等到js引擎空闲时立即被执行.

以上整个ajax请求过程中, 有涉及到浏览器的4种线程. 其中除了 GUI渲染线程js引擎线程 是互斥的. 其他线程相互之间, 都是可以并行执行的. 通过这样的一种方式, ajax并没有破坏js的单线程机制.

ajax与setTimeout排队问题

通常, ajax 和 setTimeout 的事件回调都被同等的对待, 按照顺序自动的被添加到 任务队列 的末尾, 等待js引擎空闲时执行. 但请注意, 并非xhr的所有回调执行都滞后于setTImeout的回调. 请看如下代码:

function ajax(url, method){var xhr = getXHR();xhr.onreadystatechange = function(){console.log('xhr.readyState:' + this.readyState);}xhr.onloadstart = function(){console.log('onloadStart');}xhr.onload = function(){console.log('onload');}xhr.open(method, url, true);xhr.setRequestHeader('Cache-Control',3600);xhr.send();
}
var timer = setTimeout(function(){console.log('setTimeout');
},0);
ajax('https://user-gold-cdn.xitu.io/2017/3/15/c6eacd7c2f4307f34cd45e93885d1cb6.png','GET');复制代码

上述代码执行结果如下图:

ajax & setTimeout

由于ajax异步, setTimeout回调本应该最先被执行, 然而实际上, 一次ajax请求, 并非所有的部分都是异步的, 至少"readyState==1"的 onreadystatechange 回调以及 onloadstart 回调就是同步执行的. 因此它们的输出排在最前面.

XMLHttpRequest 属性解读

首先在Chrome console下创建一个 XMLHttpRequest 实例对象xhr. 如下所示:

XMLHttpRequest

inherit

试运行以下代码.

var xhr = new XMLHttpRequest(),i=0;
for(var key in xhr){if(xhr.hasOwnProperty(key)){i++;}
}
console.log(i);//0
console.log(XMLHttpRequest.prototype.hasOwnProperty('timeout'));//true复制代码

可见, XMLHttpRequest 实例对象没有自有属性. 实际上, 它的所有属性均来自于 XMLHttpRequest.prototype .

追根溯源, XMLHttpRequest 实例对象具有如下的继承关系. (下面以a<<b表示a继承b)

xhr << XMLHttpRequest.prototype << XMLHttpRequestEventTarget.prototype << EventTarget.prototype << Object.prototype

由上, xhr也具有Object等原型中的所有方法. 如toString方法.

xhr.toString();//"[object XMLHttpRequest]"复制代码

通常, 一个xhr实例对象拥有10个普通属性+9个方法.

readyState

只读属性, readyState属性记录了ajax调用过程中所有可能的状态. 它的取值简单明了, 如下:

readyState对应常量描述
0 (未初始化)xhr.UNSENT请求已建立, 但未初始化(此时未调用open方法)
1 (初始化)xhr.OPENED请求已建立, 但未发送 (已调用open方法, 但未调用send方法)
2 (发送数据)xhr.HEADERS_RECEIVED请求已发送 (send方法已调用, 已收到响应头)
3 (数据传送中)xhr.LOADING请求处理中, 因响应内容不全, 这时通过responseBody和responseText获取可能会出现错误
4 (完成)xhr.DONE数据接收完毕, 此时可以通过通过responseBody和responseText获取完整的响应数据

注意, readyState 是一个只读属性, 想要改变它的值是不可行的.

onreadystatechange

onreadystatechange事件回调方法在readystate状态改变时触发, 在一个收到响应的ajax请求周期中, onreadystatechange 方法会被触发4次. 因此可以在 onreadystatechange 方法中绑定一些事件回调, 比如:

xhr.onreadystatechange = function(e){if(xhr.readystate==4){var s = xhr.status;if((s >= 200 && s < 300) || s == 304){var resp = xhr.responseText;//TODO ...}}
}复制代码

注意: onreadystatechange回调中默认会传入Event实例, 如下:

Event

status

只读属性, status表示http请求的状态, 初始值为0. 如果服务器没有显式地指定状态码, 那么status将被设置为默认值, 即200.

statusText

只读属性, statusText表示服务器的响应状态信息, 它是一个 UTF-16 的字符串, 请求成功且status==20X时, 返回大写的 OK . 请求失败时返回空字符串. 其他情况下返回相应的状态描述. 比如: 301的 Moved Permanently , 302的 Found , 303的 See Other , 307 的 Temporary Redirect , 400的 Bad Request , 401的 Unauthorized 等等.

onloadstart

onloadstart事件回调方法在ajax请求发送之前触发, 触发时机在 readyState==1 状态之后, readyState==2 状态之前.

onloadstart方法中默认将传入一个ProgressEvent事件进度对象. 如下:

ProgressEvent

ProgressEvent对象具有三个重要的Read only属性.

  • lengthComputable 表示长度是否可计算, 它是一个布尔值, 初始值为false.
  • loaded 表示已加载资源的大小, 如果使用http下载资源, 它仅仅表示已下载内容的大小, 而不包括http headers等. 它是一个无符号长整型, 初始值为0.
  • total 表示资源总大小, 如果使用http下载资源, 它仅仅表示内容的总大小, 而不包括http headers等, 它同样是一个无符号长整型, 初始值为0.

onprogress

onprogress事件回调方法在 readyState==3 状态时开始触发, 默认传入 ProgressEvent 对象, 可通过 e.loaded/e.total 来计算加载资源的进度, 该方法用于获取资源的下载进度.

注意: 该方法适用于 IE10+ 及其他现代浏览器.

xhr.onprogress = function(e){console.log('progress:', e.loaded/e.total);
}复制代码

onload

onload事件回调方法在ajax请求成功后触发, 触发时机在 readyState==4 状态之后.

想要捕捉到一个ajax异步请求的成功状态, 并且执行回调, 一般下面的语句就足够了:

xhr.onload = function(){var s = xhr.status;if((s >= 200 && s < 300) || s == 304){var resp = xhr.responseText;//TODO ...}
}复制代码

onloadend

onloadend事件回调方法在ajax请求完成后触发, 触发时机在 readyState==4 状态之后(收到响应时) 或者 readyState==2 状态之后(未收到响应时).

onloadend方法中默认将传入一个ProgressEvent事件进度对象.

timeout

timeout属性用于指定ajax的超时时长. 通过它可以灵活地控制ajax请求时间的上限. timeout的值满足如下规则:

  • 通常设置为0时不生效.
  • 设置为字符串时, 如果字符串中全部为数字, 它会自动将字符串转化为数字, 反之该设置不生效.
  • 设置为对象时, 如果该对象能够转化为数字, 那么将设置为转化后的数字.
xhr.timeout = 0; //不生效
xhr.timeout = '123'; //生效, 值为123
xhr.timeout = '123s'; //不生效
xhr.timeout = ['123']; //生效, 值为123
xhr.timeout = {a:123}; //不生效复制代码

ontimeout

ontimeout方法在ajax请求超时时触发, 通过它可以在ajax请求超时时做一些后续处理.

xhr.ontimeout = function(e) {console.error("请求超时!!!")
}复制代码

response responseText

均为只读属性, response表示服务器的响应内容, 相应的, responseText表示服务器响应内容的文本形式.

responseXML

只读属性, responseXML表示xml形式的响应数据, 缺省为null, 若数据不是有效的xml, 则会报错.

responseType

responseType表示响应的类型, 缺省为空字符串, 可取 "arraybuffer" , "blob" , "document" , "json" , and "text" 共五种类型.

responseURL

responseURL返回ajax请求最终的URL, 如果请求中存在重定向, 那么responseURL表示重定向之后的URL.

withCredentials

withCredentials是一个布尔值, 默认为false, 表示跨域请求中不发送cookies等信息. 当它设置为true时, cookies , authorization headers 或者TLS客户端证书 都可以正常发送和接收. 显然它的值对同域请求没有影响.

注意: 该属性适用于 IE10+, opera12+及其他现代浏览器.

abort

abort方法用于取消ajax请求, 取消后, readyState 状态将被设置为 0 (UNSENT). 如下, 调用abort 方法后, 请求将被取消.

Event

getResponseHeader

getResponseHeader方法用于获取ajax响应头中指定name的值. 如果response headers中存在相同的name, 那么它们的值将自动以字符串的形式连接在一起.

console.log(xhr.getResponseHeader('Content-Type'));//"text/html"复制代码

getAllResponseHeaders

getAllResponseHeaders方法用于获取所有安全的ajax响应头, 响应头以字符串形式返回. 每个HTTP报头名称和值用冒号分隔, 如key:value, 并以\r\n结束.

xhr.onreadystatechange = function() {if(this.readyState == this.HEADERS_RECEIVED) {console.log(this.getAllResponseHeaders());}
}
//Content-Type: text/html"复制代码

以上, readyState === 2 状态时, 就意味着响应头已接受完整. 此时便可以打印出完整的 response headers.

setRequestHeader

既然可以获取响应头, 那么自然也可以设置请求头, setRequestHeader就是干这个的. 如下:

//指定请求的type为json格式
xhr.setRequestHeader("Content-type", "application/json");
//除此之外, 还可以设置其他的请求头
xhr.setRequestHeader('x-requested-with', '123456');复制代码

onerror

onerror方法用于在ajax请求出错后执行. 通常只在网络出现问题时或者ERR_CONNECTION_RESET时触发(如果请求返回的是407状态码, chrome下也会触发onerror).

upload

upload属性默认返回一个 XMLHttpRequestUpload 对象, 用于上传资源. 该对象具有如下方法:

  • onloadstart
  • onprogress
  • onabort
  • onerror
  • onload
  • ontimeout
  • onloadend

上述方法功能同 xhr 对象中同名方法一致. 其中, onprogress 事件回调方法可用于跟踪资源上传的进度.

xhr.upload.onprogress = function(e){var percent = 100 * e.loaded / e.total |0;console.log('upload: ' + precent + '%');
}复制代码

overrideMimeType

overrideMimeType方法用于强制指定response 的 MIME 类型, 即强制修改response的 Content-Type . 如下, 服务器返回的response的 MIME 类型为 text/plain .

response headers

xhr.getResponseHeader('Content-Type');//"text/plain"
xhr.responseXML;//null复制代码

通过overrideMimeType方法将response的MIME类型设置为 text/xml;charset=utf-8 , 如下所示:

xhr.overrideMimeType("text/xml; charset = utf-8");
xhr.send();复制代码

此时虽然 response headers 如上图, 没有变化, 但 Content-Type 已替换为新值.

xhr.getResponseHeader('Content-Type');//"text/xml; charset = utf-8"复制代码

此时, xhr.responseXML 也将返回DOM对象, 如下图.

response headers

XHR一级

XHR1 即 XMLHttpRequest Level 1. XHR1时, xhr对象具有如下缺点:

  • 仅支持文本数据传输, 无法传输二进制数据.
  • 传输数据时, 没有进度信息提示, 只能提示是否完成.
  • 受浏览器 同源策略 限制, 只能请求同域资源.
  • 没有超时机制, 不方便掌控ajax请求节奏.

XHR二级

XHR2 即 XMLHttpRequest Level 2. XHR2针对XHR1的上述缺点做了如下改进:

  • 支持二进制数据, 可以上传文件, 可以使用FormData对象管理表单.
  • 提供进度提示, 可通过 xhr.upload.onprogress 事件回调方法获取传输进度.
  • 依然受 同源策略 限制, 这个安全机制不会变. XHR2新提供 Access-Control-Allow-Origin 等headers, 设置为 * 时表示允许任何域名请求, 从而实现跨域CORS访问(有关CORS详细介绍请耐心往下读).
  • 可以设置timeout 及 ontimeout, 方便设置超时时长和超时后续处理.

这里就H5新增的FormData对象举个例.

//可直接创建FormData实例
var data = new FormData();
data.append("name", "louis");
xhr.send(data);
//还可以通过传入表单DOM对象来创建FormData实例
var form = document.getElementById('form');
var data = new FormData(form);
data.append("password", "123456");
xhr.send(data);复制代码

目前, 主流浏览器基本上都支持XHR2, 除了IE系列需要IE10及更高版本. 因此IE10以下是不支持XHR2的.

那么问题来了, IE7, 8,9的用户怎么办? 很遗憾, 这些用户是比较尴尬的. 对于IE8,9而言, 只有一个阉割版的 XDomainRequest 可用,IE7则没有. 估计IE7用户只能哭晕在厕所了.

XDomainRequest

XDomainRequest 对象是IE8,9折腾出来的, 用于支持CORS请求非成熟的解决方案. 以至于IE10中直接移除了它, 并重新回到了 XMLHttpRequest 的怀抱.

XDomainRequest 仅可用于发送 GETPOST 请求. 如下即创建过程.

var xdr = new XDomainRequest();复制代码

xdr具有如下属性:

  • timeout
  • responseText

如下方法:

  • open: 只能接收Method,和url两个参数. 只能发送异步请求.
  • send
  • abort

如下事件回调:

  • onprogress
  • ontimeout
  • onerror
  • onload

除了缺少一些方法外, XDomainRequest 基本上就和 XMLHttpRequest 的使用方式保持一致.

必须要明确的是:

  • XDomainRequest 不支持跨域传输cookie.
  • 只能设置请求头的Content-Type字段, 且不能访问响应头信息.

$.ajax

$.ajax是jquery对原生ajax的一次封装. 通过封装ajax, jquery抹平了不同版本浏览器异步http的差异性, 取而代之的是高度统一的api. jquery作为js类库时代的先驱, 对前端发展有着深远的影响. 了解并熟悉其ajax方法, 不可谓不重要.

参数列表

$.ajax() 只有一个参数, 该参数为key-value设置对象. 实际上, jq发送的所有ajax请求, 都是通过调用该ajax方法实现的. 它的详细参数如下表:

序号参数类型描述
1acceptsPlainObject用于通知服务器该请求需要接收何种类型的返回结果. 如有必要, 推荐在 $.ajaxSetup()方法中设置一次.
2asyncBoolean默认为true, 即异步.
3beforeSendFunction请求发送前的回调, 默认传入参数jqXHR和settings. 函数内显式返回false将取消本次请求.
4cacheBoolean请求是否开启缓存, 默认为true, 如不需要缓存请设置为false. 不过, dataType为"script"和"jsonp"时默认为false.
5completeFunction请求完成后的回调(请求success 和 error之后均调用), 默认传入参数jqXHR和textStatus(请求状态, 取值为 "success","notmodified","error","timeout","abort","parsererror"之一). 从jq1.5开始, complete可以设置为一个包含函数的数组. 如此每个函数将依次被调用.
6contentsPlainObject一个以"{字符串/正则表达式}"配对的对象, 根据给定的内容类型, 解析请求的返回结果.
7contentTypeString编码类型, 相对应于http请求头域的"Content-Type"字段. 默认值为"application/x-www-form-urlencoded; charset=UTF-8".
8contextObject设置ajax回调函数的上下文. 默认上下文为ajax请求传入的参数设置对象. 如设置为document.body, 那么所有ajax回调函数中将以body为上下文.
9convertersPlainObject一个数据类型到数据类型转换器的对象. 默认为 {"* text": window.String, "text html": true, "text json": jQuery.parseJSON, "text xml": jQuery.parseXML} . 如设置converters:{"json jsonp": function(msg){}}
10crossDomainBoolean默认同域请求为false, 跨域请求为true.
11dataObject, Array发送到服务器的数据, 默认data为键值对格式对象, 若data为数组则按照traditional参数的值, 自动转化为一个同名的多值查询字符串. 如{a:1,b:2}将转换为"&a=1&b=2".
12dataFilterFunction处理XMLHttpRequest原始响应数据的回调, 默认传入data和type参数, data是Ajax返回的原始数据, type是调用$.ajax时提供的dataType参数
13dataTypeString预期服务器返回的数据类型, 可设置为"xml","html","script","json","jsonp","text"之一, 其中设置为"xml"或"text"类型时, 数据不会经过处理.
14errorFunction请求失败时的回调函数, 默认传入jqXHR(jq1.4以前为原生xhr对象),textStatus(请求状态,取值为null,"timeout","error","abort" 或 "parsererror"),errorString(错误内容), 当一个HTTP错误发生时, errorThrown 接收HTTP状态的文本部分,比如"Not Found"等. 从jq1.5开始, error可以设置为一个包含函数的数组. 如此每个函数将依次被调用.注意: 跨域脚本和JSONP请求时error不被调用.
15globalBoolean表示是否触发全局ajax事件, 默认为true. 设为false将不再触发ajaxStart,ajaxStop,ajaxSend,ajaxError等. 跨站脚本和jsonp请求, 该值自动设置为false.
16headersPlainObject设置请求头, 格式为k-v键值对对象. 由于该设置会在beforeSend函数被调用之前生效, 因此可在beforeSend函数内覆盖该对象.
17ifModifiedBoolean只有上次请求响应改变时, 才允许请求成功. 它使用HTTP包的Last-Modified 头信息判断, 默认为false. 若设置为true, 且数据自从上次请求后没有更改过就会报错.
18isLocalBoolean运行当前环境设置为"本地",默认为false, 若设置为true, 将影响请求发送时的协议.
19jsonpString显式指定jsonp请求中的回调函数的名称. 如jsonp:cb, jq会将cb代替callback, 以 "cb=?"传给服务器. 从jq1.5开始, 若设置jsonp:false, 那么需要明确设置jsonpCallback:"callbackName".
20jsonpCallbackString,Function为jsonp请求指定一个回调函数名, 以取代jq自动生成的随机函数名. 从jq1.5开始, 可以将该属性设置为一个函数, 函数的返回值就是jsonpCallback的结果.
21mimeTypeString设置一个MIME类型, 以覆盖xhr的MIM类型(jq1.5新增)
22passwordString设置认证请求中的密码
23processDataBooleanjq的ajax方法默认会将传入的data隐式转换为查询字符串(如"&a=1&b=2"), 以配合 默认内容类型 "application/x-www-form-urlencoded", 如果不希望转换请设置为false. angular中想要禁用默认转换, 需要重写transformRequest方法.
24scriptCharsetString仅在"script"请求中使用(如跨域jsonp, dataType为"script"类型). 显式指定时, 请求中将在script标签上设置charset属性, 可在发现本地和远程编码不一致时使用.
25statusCodePlainObject一组http状态码和回调函数对应的键值对对象. 该对象以 {404:function(){}} 这种形式表示. 可用于根据不同的http状态码, 执行不同的回调.(jq1.5新增)
26timeoutNumber设置超时时间.
27traditionalBoolean是否按照默认方式序列化data对象, 默认值为false.
28typeString可以设置为8种http method之一, jq中不区分大小写.
29urlString请求的uri地址.
30usernameString设置认证请求中的用户名
31xhrFunction在回调内创建并返回xhr对象
32xhrFieldsPlainObject键值对对象, 用于设置原生的xhr对象, 如可用来设置withCredentials:true(jq1.5.1新增)

支持promise

$.ajax() 方法返回jqXHR对象(jq1.5起), 如果使用的不是XMLHttpRequest对象时, 如jsonp请求, 返回的jqXHR对象将尽可能模拟原生的xhr. 从jq1.5起, 返回的jqXHR对象实现了promise接口, 具有如下新方法.

新方法被替代的老方法(jq1.8起弃用)
done(function(data, textStatus, jqXHR) {})success
fail(function(jqXHR, textStatus, errorThrown) {})error
always(function(data or jqXHR, textStatus, jqXHR or errorThrown) {})complete

从jq1.6开始, done, fail, always按照FIFO队列可以分配多个回调.

使用转换器

$.ajax() 的转换器可以将支持的数据类型映射到其它数据类型. 如果需要将自定义数据类型映射到已知的类型. 需要使用 contents 选项在响应的 "Content-Type" 和实际数据类型之间添加一个转换函数.

$.ajaxSetup({contents: {myContentType: /myContentType/},converters: {"myContentType json": function(data) {//TODO somethingreturn newData;}}
});复制代码

转换一个支持的类型为自定义类型, 然后再返回. 如 text—>myContentType—>json.

$.ajaxSetup({contents: {myContentType: /myContentType/},converters: {"text myContentType": true,"myContentType json": function(data) {//TODO somethingreturn newData;}}
});复制代码

事件触发顺序

$.ajax()方法触发的事件纷繁复杂, 有将近20个之多. 为了囊括最多的事件, 这里以一次成功的上传请求为例, 以下是它们的调用顺序(请求出现错误时的顺序, 请自行对应).

序号事件名称是否全局事件是否能关闭默认形参
1$.ajaxPrefilter✔️❌function(options, originalOptions, jqXHR){}
2$(document).ajaxStar✔️✔️function(){}(只在当前无激活ajax时触发)
3beforeSend❌-function(jqXHR, settings){}
4$(document).ajaxSend✔️✔️function(){}
5xhr.onloadstart--ProgressEvent
6xhr.upload.onloadstart--ProgressEvent
7xhr.upload.onprogress--ProgressEvent
8xhr.upload.onload--ProgressEvent
9xhr.upload.onloadend--ProgressEvent
10xhr.onprogress--ProgressEvent
11xhr.onload--ProgressEvent
12success(弃用)❌-function(data, textStatus, jqXHR){}
13$(document).ajaxSuccess✔️✔️function(event, jqXHR, options){}
14complete(弃用)❌-function(jqXHR, textStatus){}
15$(document).ajaxComplete✔️✔️function(event, jqXHR, textStatus)
16$(document).ajaxStop✔️✔️function(){}
17xhr.onloadend--ProgressEvent

从jq1.8起, 对于函数 ajaxStart, ajaxSend, ajaxSuccess, ajaxComplete, ajaxStop , 只能为document对象绑定事件处理函数, 为其他元素绑定的事件处理函数不会起作用.

Axios

实际上, 如果你仅仅只是想要一个不错的http库, 相比于庞大臃肿的jquery, 短小精悍的Axios可能更加适合你. 原因如下:

  • Axios支持node, jquery并不支持.
  • Axios基于promise语法, jq3.0才开始全面支持.
  • Axios短小精悍, 更加适合http场景, jquery大而全, 加载较慢.
  • vue作者尤大放弃推荐vue-resource, 转向推荐Axios. 以下为尤大原话.

"最近团队讨论了一下, Ajax 本身跟 Vue 并没有什么需要特别整合的地方, 使用 fetch polyfill 或是 axios、superagent 等等都可以起到同等的效果, vue-resource 提供的价值和其维护成本相比并不划算, 所以决定在不久以后取消对 vue-resource 的官方推荐."

Axios大小仅12k, 目前最新版本号为:

语法上Axios基本就和promise一样, 在then方法中处理回调, 在catch方法中处理异常. 如下:

axios.get("https://api.github.com/users/louiszhai").then(function(response){console.log(response);}).catch(function (error) {console.log(error);});复制代码

除了get, 它还支持post, delete, head, put, patch, request请求. 具体使用攻略, 请戳这里: axios .

如需在网页上引入 Axios, 可以链接CDN axios | Bootstrap中文网开源项目免费 CDN 服务 或者将其下载到本地.

Fetch

说到ajax, 就不得不提及fetch, 由于篇幅较长, fetch已从本文中独立出来, 请戳 Fetch进阶指南 .

ajax跨域请求什么是CORS

CORS是一个W3C(World Wide Web)标准, 全称是跨域资源共享(Cross-origin resource sharing).它允许浏览器向跨域服务器, 发出异步http请求, 从而克服了ajax受同源策略的限制. 实际上, 浏览器不会拦截不合法的跨域请求, 而是拦截了他们的响应, 因此即使请求不合法, 很多时候, 服务器依然收到了请求.(Chrome和Firefox下https网站不允许发送http异步请求除外)

通常, 一次跨域访问拥有如下流程:

移动端CORS兼容性

当前几乎所有的桌面浏览器(Internet Explorer 8+, Firefox 3.5+, Safari 4+和 Chrome 3+)都可通过名为跨域资源共享的协议支持ajax跨域调用.

那么移动端兼容性又如何呢? 请看下图:

cors-mobile

可见, CORS的技术在IOS Safari7.1及Android webview2.3中就早已支持, 即使低版本下webview的canvas在使用跨域的video或图片时会有问题, 也丝毫不影响CORS的在移动端的使用. 至此, 我们就可以放心大胆的去应用CORS了.

CORS有关的headers

1) HTTP Response Header(服务器提供):

  • Access-Control-Allow-Origin: 指定允许哪些源的网页发送请求.

  • Access-Control-Allow-Credentials: 指定是否允许cookie发送.

  • Access-Control-Allow-Methods: 指定允许哪些请求方法.

  • Access-Control-Allow-Headers: 指定允许哪些常规的头域字段, 比如说 Content-Type.

  • Access-Control-Expose-Headers: 指定允许哪些额外的头域字段, 比如说 X-Custom-Header.

    该字段可省略. CORS请求时, xhr.getResponseHeader() 方法默认只能获取6个基本字段: Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma . 如果需要获取其他字段, 就需要在Access-Control-Expose-Headers 中指定. 如上, 这样xhr.getResponseHeader('X-Custom-Header') 才能返回X-Custom-Header字段的值.(该部分摘自阮一峰老师博客)

  • Access-Control-Max-Age: 指定preflight OPTIONS请求的有效期, 单位为秒.

2) HTTP Request Header(浏览器OPTIONS请求默认自带):

  • Access-Control-Request-Method: 告知服务器,浏览器将发送哪种请求, 比如说POST.
  • Access-Control-Request-Headers: 告知服务器, 浏览器将包含哪些额外的头域字段.

3) 以下所有的header name 是被拒绝的:

  • Accept-Charset
  • Accept-Encoding
  • Access-Control-Request-Headers
  • Access-Control-Request-Method
  • Connection
  • Content-Length
  • Cookie
  • Cookie2
  • Date
  • DNT
  • Expect
  • Host
  • Keep-Alive
  • Origin
  • Referer
  • TE
  • Trailer
  • Transfer-Encoding
  • Upgrade
  • Via
  • 包含以Proxy-Sec- 开头的header name

CORS请求

CORS请求分为两种, ① 简单请求; ② 非简单请求.

满足如下两个条件便是简单请求, 反之则为非简单请求.(CORS请求部分摘自阮一峰老师博客)

1) 请求是以下三种之一:

  • HEAD
  • GET
  • POST

2) http头域不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type字段限三个值 application/x-www-form-urlencodedmultipart/form-datatext/plain

对于简单请求, 浏览器将发送一次http请求, 同时在Request头域中增加 Origin 字段, 用来标示请求发起的源, 服务器根据这个源采取不同的响应策略. 若服务器认为该请求合法, 那么需要往返回的 HTTP Response 中添加 Access-Control-* 等字段.( Access-Control-* 相关字段解析请阅读我之前写的CORS 跨域访问 )

对于非简单请求, 比如Method为POST且Content-Type值为 application/json 的请求或者Method为 PUTDELETE 的请求, 浏览器将发送两次http请求. 第一次为preflight预检(Method: OPTIONS),主要验证来源是否合法. 值得注意的是:OPTION请求响应头同样需要包含 Access-Control-* 字段等. 第二次才是真正的HTTP请求. 所以服务器必须处理OPTIONS应答(通常需要返回20X的状态码, 否则xhr.onerror事件将被触发).

以上请求流程图为:

HTML启用CORS

http-equiv 相当于http的响应头, 它回应给浏览器一些有用的信息,以帮助正确和精确地显示网页内容. 如下html将允许任意域名下的网页跨域访问.

<meta http-equiv="Access-Control-Allow-Origin" content="*">复制代码

图片启用CORS

通常, 图片允许跨域访问, 也可以在canvas中使用跨域的图片, 但这样做会污染画布, 一旦画布受污染, 将无法读取其数据. 比如无法调用 toBlob(), toDataURL() 或 getImageData()方法. 浏览器的这种安全机制规避了未经许可的远程服务器图片被滥用的风险.(该部分内容摘自 启用了 CORS 的图片 - HTML(超文本标记语言) | MDN)

因此如需在canvas中使用跨域的图片资源, 请参考如下apache配置片段(来自HTML5 Boilerplate Apache server configs).

<IfModule mod_setenvif.c><IfModule mod_headers.c><FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">SetEnvIf Origin ":" IS_CORSHeader set Access-Control-Allow-Origin "*" env=IS_CORS</FilesMatch></IfModule>
</IfModule>复制代码

ajax文件上传

ajax实现文件上传非常简单, 这里我选取原生js, jq, angular 分别来比较下, 并顺便聊聊使用它们时的注意事项.(ajax文件上传的代码已上传至github, 请戳这里预览效果: ajax 文件上传 demo | louis)

1) 为了上传文件, 我们得先选中一个文件. 一个type为file的input框就够了.

<input id="input" type="file">复制代码

2) 然后用FormData对象包裹?选中的文件.

var input = document.getElementById("input"),formData = new FormData();
formData.append("file",input.files[0]);//key可以随意定义,只要后台能理解就行复制代码

3) 定义上传的URL, 以及方法. github上我搭建了一个 node-webserver, 根据需要可以自行克隆下来npm start后便可调试本篇代码.

var url = "http://localhost:10108/test",method = "POST";复制代码

js文件上传

4.1) 封装一个用于发送ajax请求的方法.

function ajax(url, method, data){var xhr = null;if(window.XMLHttpRequest) {xhr = new XMLHttpRequest();} else if (window.ActiveXObject) {try {xhr = new ActiveXObject("Msxml2.XMLHTTP");} catch (e) {try {xhr = new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { alert("您的浏览器暂不支持Ajax!");}}}xhr.onerror = function(e){console.log(e);}xhr.open(method, url);try{setTimeout(function(){xhr.send(data);});}catch(e){console.log('error:',e);}return xhr;
}复制代码

4.2) 上传文件并绑定事件.

var xhr = ajax(url, method, formData);
xhr.upload.onprogress = function(e){console.log("upload progress:", e.loaded/e.total*100 + "%");
};
xhr.upload.onload = function(){console.log("upload onload.");
};
xhr.onload = function(){console.log("onload.");
}复制代码

上传结果如下所示:

js file upload

fetch上传

5) fetch只要发送一个post请求, 并且body属性设置为formData即可. 遗憾的是, fetch无法跟踪上传的进度信息.

fetch(url, {method: method,body: formData}).then(function(res){console.log(res);}).catch(function(e){console.log(e);
});复制代码

jquery文件上传

jq提供了各式各样的上传插件, 其原理都是利用jq自身的ajax方法.

6) jq的ajax提供了xhr属性用于自定义各种事件.

$.ajax({type: method,url: url,data: formData,processData : false,contentType : false ,//必须false才会自动加上正确的Content-Typexhr: function(){var xhr = $.ajaxSettings.xhr();//实际上就是return new window.XMLHttpRequest()对象if(xhr.upload) {xhr.upload.addEventListener("progress", function(e){console.log("jq upload progress:", e.loaded/e.total*100 + "%");}, false);xhr.upload.addEventListener("load", function(){console.log("jq upload onload.");});xhr.addEventListener("load", function(){console.log("jq onload.");});return xhr;}}
});复制代码

jq上传结果如下所示:

jq file upload

有关jq ajax更多的api, 请参考中文文档 jQuery.ajax() | jQuery API 中文文档 .

angular文件上传

7.1) angular提供了$http方法用于发送http请求, 该方法返回一个promise对象.

$http({method: method,url: url,data: formData,
}).success(function(res) {console.log(res);
}).error(function(err, status) {console.log(err);
});复制代码

angular文件上传的代码已上传至github, 请戳这里预览效果: angular 文件上传 demo | louis.

低版本angular中文件上传的功能并不完整, 直到angular1.5.5才在$http中加入了eventHandler和uploadEventHandlers等方法, 使得它支持上传进度信息. 如下:

$http({method: method,url: url,eventHandlers: {progress: function(c) {//下载进度console.log('Progress -> ' + c);}},uploadEventHandlers: {progress: function(e) {//上传进度console.log('UploadProgress -> ' + e);}},data: formData,
}).success(function(res) {console.log(res);
}).error(function(err, status) {console.log(err);
});复制代码

angular1.5.5以下低版本中, 请参考成熟的实现方案 angular-file-upload 以及它提供的demo Simple example .

ajax请求二进制文件FileReader

处理二进制文件主要使用的是H5的FileReader.

PC支持性如下:

IEEdgeFirefoxChromeSafariOpera
10123.66611.5

Mobile支持性如下:

IOS SafariOpera MiniAndroid BrowserChrome/AndroidUC/Android
7.1-45311

以下是其API:

属性/方法名称描述
error表示读取文件期间发生的错误.
readyState表示读取文件的状态.默认有三个值:0表示文件还没有加载;1表示文件正在读取;2表示文件读取完成.
result读取的文件内容.
abort()取消文件读取操作, 此时readyState属性将置为2.
readAsArrayBuffer()读取文件(或blob对象)为类型化数组(ArrayBuffer), 类型化数组允许开发者以数组下标的方式, 直接操作内存, 由于数据以二进制形式传递, 效率非常高.
readAsBinaryString()读取文件(或blob对象)为二进制字符串, 该方法已移出标准api, 请谨慎使用.
readAsDataURL()读取文件(或blob对象)为base64编码的URL字符串, 与window.URL.createObjectURL方法效果类似.
readAsText()读取文件(或blob对象)为文本字符串.
onload()文件读取完成时的事件回调, 默认传入event事件对象. 该回调内, 可通过this.result 或 event.target.result获取读取的文件内容.

ajax请求二进制图片并预览

var xhr = new XMLHttpRequest(),url = "https://user-gold-cdn.xitu.io/2017/3/15/c6eacd7c2f4307f34cd45e93885d1cb6.png";
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.onload = function(){if(this.status == 200){var blob = this.response;var img = document.createElement("img");//方案一img.src = window.URL.createObjectURL(blob);//这里blob依然占据着内存img.onload = function() {window.URL.revokeObjectURL(img.src);//释放内存};//方案二/*var reader = new FileReader();reader.readAsDataURL(blob);//FileReader将返回base64编码的data-uri对象reader.onload = function(){img.src = this.result;}*///方案三//img.src = url;//最简单方法document.body.appendChild(img);}
}
xhr.send();复制代码

ajax请求二进制文本并展示

var xhr = new XMLHttpRequest();
xhr.open("GET","http://localhost:8080/Information/download.jsp?data=node-fetch.js");
xhr.responseType = "blob";
xhr.onload = function(){if(this.status == 200){var blob = this.response;var reader = new FileReader();reader.readAsBinaryString(blob);//该方法已被移出标准api,建议使用reader.readAsText(blob);reader.onload=function(){document.body.innerHTML = "<div>" + this.result + "</div>";}}
}
xhr.send();复制代码

有关二进制文件的读取, 请移步这篇博客 HTML5新特性之文件和二进制数据的操作 .

如何等待多个ajax请求完成

原生js可以使用ES6新增的Promise. ES6的Promise基于 Promises/A+ 规范(该部分 Fetch入门指南 一文也有提及).

这里先提供一个解析responses的函数.

function todo(responses){responses.forEach(function(response){response.json().then(function(res){console.log(res);});});
}复制代码

原生js使用 Promise.all 方法. 如下:

var p1 = fetch("http://localhost:10108/test1"),p2 = fetch("http://localhost:10108/test2");
Promise.all([p1, p2]).then(function(responses){todo(responses);//TODO do somethings
});
//"test1"
//"test2"复制代码

jquery可以使用$.when方法. 该方法接受一个或多个Deferred对象作为参数, 只有全部成功才调用resolved状态的回调函数, 但只要其中有一个失败,就调用rejected状态的回调函数. 其实, jq的Deferred是基于 Promises/A规范实现, 但并非完全遵循. (传送门: jQuery 中的 Deferred 和 Promises (2) ).

var p1 = $.ajax("http://localhost:10108/test1"),p2 = $.ajax("http://localhost:10108/test2");
$.when(p1, p2).then(function(res1, res2){console.log(res1);//["test1", "success", Object]console.log(res2);//["test2", "success", Object]//TODO do somethings
});复制代码

如上, $.when默认返回一个jqXHR对象, 可以直接进行链式调用. then方法的回调中默认传入相应的请求结果, 每个请求结果的都是数组, 数组中依次是responseText, 请求状态, 请求的jqXHR对象.

angular中可以借助 $q.all() 来实现. 别忘了, $q 需要在controller中注入. 此外, $q 相关讲解可参考 AngularJS: ng.$q 或 Angular $q service学习笔记 .

var p1 = fetch("http://localhost:10108/test1"),p2 = fetch("http://localhost:10108/test2");
$q.all([p1, p2]).then(function(responses){todo(responses);//TODO do somethings
});
//"test1"
//"test2"复制代码

$q.all() 实际上就是对 Promise.all 的封装.

ajax与history的兼容

ajax的一大痛点就是无法支持浏览器前进和后退操作. 因此早期的Gmail 采用 iframe, 来模拟ajax的前进和后退.

如今, H5普及, pjax大行其道. pajax 就是 ajax+history.pushState 组合的一种技术. 使用它便可以无刷新通过浏览器前进和后退来改变页面内容.

先看下兼容性.

IEEdgeFirefoxChromeSafariOperaiOS SafariAndroid BrowserChrome for Android
pushState/replaceState101245611.57.14.353
history.state10418611.5

可见IE8,9并不能使用 H5的history. 需要使用垫片 HTML5 History API expansion for browsers not supporting pushState, replaceState .

pjax

pjax简单易用, 仅需要如下三个api:

  • history.pushState(obj, title, url) 表示往页面history末尾新增一个历史项(history entry), 此时history.length会+1.
  • history.replaceState(obj, title, url) 表示替换当前历史项为新的历史项. 此时history.length保持不变.
  • window.onpopstate 仅在浏览器前进和后退时触发(history.go(1), history.back() 及location.href="xxx" 均会触发), 此时可在history.state中拿到刚刚塞进去的state, 即obj对象(其他数据类型亦可).

我们注意到, 首次进入一个页面, 此时 history.length 值为1, history.state 为空. 如下:

history.state

1) 为了在onpopstate事件回调中每次都能拿到 history.state , 此时需要在页面载入完成后, 自动替换下当前url.

history.replaceState("init", title, "xxx.html?state=0");复制代码

2) 每次发送ajax请求时, 在请求完成后, 调用如下, 从而实现浏览器history往前进.

history.pushState("ajax请求相关参数", title, "xxx.html?state=标识符");复制代码

3) 浏览器前进和后退时, popstate 事件会自动触发, 此时我们手动取出 history.state , 构建参数并重新发送ajax请求或者直接取用state值, 从而实现无刷新还原页面.

window.addEventListener("popstate", function(e) {var currentState = history.state;//TODO 拼接ajax请求参数并重新发送ajax请求, 从而回到历史页面//TODO 或者从state中拿到关键值直接还原历史页面
});复制代码

popstate 事件触发时, 默认会传入 PopStateEvent 事件对象. 该对象具有如下属性.

PopStateEvent

如有不懂, 更详细讲解请移步 : ajax与HTML5 history pushState/replaceState实例 « 张鑫旭-鑫空间-鑫生活 .

ajax缓存处理

js中的http缓存没有开关, 受制于浏览器http缓存策略. 原生xhr请求中, 可通过如下设置关闭缓存.

xhr.setRequestHeader("If-Modified-Since","0");
xhr.setRequestHeader("Cache-Control","no-cache");
//或者 URL 参数后加上  "?timestamp=" + new Date().getTime()复制代码

jquery的http缓存是否开启可通过在settings中指定cache.

$.ajax({url : 'url',dataType : "xml",cache: true,//true表示缓存开启, false表示缓存不开启success : function(xml, status){    }
});复制代码

同时jquery还可以全局设置是否缓存. 如下将全局关闭ajax缓存.

$.ajaxSetup({cache:false});复制代码

除此之外, 调试过程中出现的浏览器缓存尤为可恶. 建议开启隐私浏览器或者勾选☑️控制台的 Disable cache 选项. (这里以Chrome举例, 其他浏览器类似)

PopStateEvent

ajax的错误处理

前面已经提过, 通常只要是ajax请求收到了http状态码, 便不会进入到错误捕获里.(Chrome中407响应头除外)

实际上, $.ajax 方法略有区别, jquery的ajax方法还会在类型解析出错时触发error回调. 最常见的便是: dataType设置为json, 但是返回的data并非json格式, 此时 $.ajax 的error回调便会触发.

ajax调试技巧

有关调试, 如果接口只是做小部分修改. 那么可以使用charles(Mac) 或者fiddler(Windows), 做代理, 将请求的资源替换为本地文件, 或者使用其断点功能, 直接编辑response.

如果是新增接口的调试, 可以本地搭建node服务. 利用hosts文件配置dns + nginx将http请求转发到本地node服务器. 简易的node调试服务器可参考我的 node-webserver . 如下举一个栗子?:

hosts+nginx+node-webserver

假设我们要调试的是 www.test.com 的GET接口. 以下所有步骤以Mac为例, 其他系统, 请自行搜索?文件路径.

1) hosts配置.

sudo vim /etc/hosts
#新增一行 127.0.0.1 www.test.com复制代码

2) nginx 配置

brew install nginx #安装
#安装成功后进入目标目录
cd /usr/local/etc/nginx/
cd servers #默认配置入口为nginx.conf.同时servers目录下*.conf文件已自动加入到配置文件列表中
vim test.conf
#粘贴如下内容
server {listen       80;server_name  www.test.com;index index.html;error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}location / {proxy_pass http://localhost:10108/;proxy_redirect off;proxy_set_header Host $host;proxy_set_header        X-Read-IP       $remote_addr;proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;}
}
#:wq保存并退出
#启动nginx
sudo nginx -s reload #如果启动了只需重启即可
sudo nginx #如果没有启动,便启动之复制代码

3) node-webServer 配置

参考 node-webserver . 启动服务前只需更改index.js, 在第9行后插入如下内容:

'get': {'/': {getKey : 'Welcome to Simple Node  WebServer!'},'接口api': '你的response内容'//插入的代码                               
},复制代码

如需在nginx中配置CORS, 请看这里: Nginx通过CORS实现跨域.

编码问题

XMLHttpRequest 返回的数据默认的字符编码是utf-8, post方法提交数据默认的字符编码也是utf-8. 若页面编码为gbk等中文编码, 那么就会产生乱码.

后端接口测试技巧

通常, 如果后端接口开发OK了, 前端同学需要通过一些手段来确认接口是能正常访问的.

使用命令测试OPTIONS请求

curl -I -X OPTIONS -H "Origin: http://example.com" http://localhost:10108/
# response
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/json;charset=UTF-8
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: x-requested-with,Content-Type
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Origin: http://example.com
Access-Control-Max-Age: 3600
Server: Node WebServer
Website: https://github.com/Louiszhai/node-webserver
Date: Fri, 21 Oct 2016 09:00:40 GMT
Connection: keep-alive
Transfer-Encoding: chunked复制代码

以上, http状态码为200, 表示允许OPTIONS请求.

GET, POST 请求与GET类似, 其他请求亦然.

curl -I -X GET -H "Origin: http://example.com" http://localhost:10108/
#HTTP/1.1 200 OK
curl -I -X POST -H "Origin: http://example.com" http://localhost:10108/test
#HTTP/1.1 200 OK复制代码

postman

除此之外, 我们还可以通过chrome的postman扩展进行测试. 请看postman素洁的界面:

postman支持所有类型的http请求, 由于其向chrome申请了cookie访问权限及所有http(s)网站的访问权限. 因此可以放心使用它进行各种网站api的测试.

同时, 强烈建议阅读本文的你升级postman的使用技巧, 这里有篇: 基于Postman的API自动化测试 , 拿走不谢.

ajax移动端兼容性

移动端的支持性比较弱, 使用需谨慎. 看表.

IOS SafariOpera MiniAndroid BrowserAndroid ChromeAndroid UC
XMLHttpRequest8.4-4.4.45311(part)
fetch--5253-

本篇为ajax而生, 通篇介绍 XMLHTTPRequest 相关的知识, 力求简明, 本欲为梳理知识, 为读者答疑解惑, 但因本人理解所限, 难免有所局限, 希望正在阅读的你取其精华去其糟粕. 谢谢.

本文就讨论这么多内容,大家有什么问题或好的想法欢迎在下方参与留言和评论.

本文作者: louis

本文链接: louiszhai.github.io/2016/11/02/…

参考文章

  • XMLHttpRequest Standard
  • XMLHttpRequest Level 2 使用指南 - 阮一峰的网络日志
  • 你真的会使用XMLHttpRequest吗? - WEB前端路上踩过的坑儿 - SegmentFault
  • ajax与HTML5 history pushState/replaceState实例 « 张鑫旭-鑫空间-鑫生活
  • 跨域资源共享 CORS 详解 - 阮一峰的网络日志
  • jQuery.ajax() | jQuery API 中文文档 -- jQuery 中文网


查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 手把手教你如何利用阿里云上传文件

    最近由于公司业务需要&#xff0c;我需要使用阿里云来保存视频文件。然后访问的话需要一个临时的url可供使用&#xff0c;这样不用担心长时间暴露签名信息和地址。但是完全没做过这个东西&#xff0c;心里是慌得一笔。手动滑稽~~~。但是也是没办法&#xff0c;硬着头皮冲啦~ 不…...

    2024/4/21 3:26:28
  2. 常见面试题总结

    参考&#xff1a; https://www.nowcoder.com/ta/front-end-interview?query&asctrue&order&tagQuery&page1 http://bigerfe.com/ https://blog.csdn.net/keyandi/article/details/89227175 https://blog.csdn.net/MingL520/article/details/88549999 https:/…...

    2024/4/21 3:26:26
  3. Elastic Search + Logstash + Kibana 初学者日志

    ELK下载https://www.elastic.co/downloads因为我用的是windows操作系统&#xff0c;所以下面的介绍都基于windows环境。功能方面应该和Linux是一样的。Getting Started with ELK for Apache Logs (这个例子展示了怎样用logstash把log发送到Elastic Search, 然后用Kibana做图形化…...

    2024/5/7 1:43:33
  4. 从零开始配置 TypeScript 项目

    关于作者本文出自于掘金的子弈&#xff0c;原文链接 从零开始配置 TypeScript 项目。以下是他的一些不错的作品&#xff0c;感兴趣的可以阅读&#xff1a;面试分享&#xff1a;两年工作经验成功面试阿里P6总结在阿里我是如何当面试官的如果觉得不错希望能够在掘金关注、点赞哦&…...

    2024/5/7 8:58:19
  5. 从JavaScript到TypeScript,Pt。 IIB:使用类,接口和混合器进行设计

    Class-based design has become such an instinct that many developers cant imagine any alternative. 基于类的设计已经成为一种本能&#xff0c;许多开发人员无法想象任何替代方案。 Fortunately for that lot, ES6 adds a class keyword to simplify the syntactical cac…...

    2024/5/6 20:31:26
  6. ROS学习笔记(三)先锋机器人的使用 — 参考 ROS wiki 和 Mobile wiki

    –参考方案&#xff1a; 找到了关于p3-dx的一些关于ROS的资料 https://github.com/ManolisCh/pioneer_p3dx https://github.com/SeRViCE-Lab/p3-dx http://wiki.ros.org/demo_pioneer 先锋机器人ROS的教程&#xff1a; https://www.youtube.com/watch?v-9NHupBPC6Y 首先…...

    2024/5/7 1:02:57
  7. 第七次迭代开发总结(AngularJS下文件上传的实现)

    第七次迭代开发总结 突然之间冒出来一个第七次迭代总结看上去挺奇怪的&#xff0c;事实上因为学校项目的关系&#xff0c;我暑假留校继续开发。在迭代的前半周期&#xff0c;团队进行了一次技术迁移&#xff0c;舍弃LiveScript转向了ECMAScript 6。有空的话会写一些ECMAScript…...

    2024/5/5 18:34:01
  8. “JavaScript Promises和AngularJS $q Service”Part 2 (教程篇)

    欢迎大家到我的博客关注我学习Ionic 1和Ionic 2的历程&#xff0c;共同学习&#xff0c;共同进步。 注&#xff1a;本文是译文&#xff0c;难免有错误或理解不足之处&#xff0c;请大家多多指正&#xff0c;大家也可挪步原文。由于本文讲解十分精彩&#xff0c;非常推荐大家查看…...

    2024/4/28 20:32:58
  9. HEVC相关文档

    转载自 ye_f最终编辑 ye_f虽然也是做编码的&#xff0c;让自己懒得写啊&#xff0c;一下材料源自http://blog.csdn.net/yuanchao99/article/details/6803856&#xff0c;谢谢啊。 •ITU官网&#xff1a; –http://www.itu.int/itu-t/workprog/wp_item.aspx?isn7752•会议文档&…...

    2024/4/21 3:26:19
  10. angularJS关于依赖和模块与amd/cmd的区别,分享下结合使用示例

    angular框架的介绍大家可以参考下官网和中文社区。 下面链接是简介&#xff1a; http://www.angularjs.cn/docs/developer/328.html 简单总结下就是&#xff1a; 双向绑定&#xff0c;可测试性的代码结构&#xff0c;模型视图分离的一个前端MV*框架 其中angular也提供了模型的概…...

    2024/5/7 9:06:06
  11. angularjs完整demo例子

    AngularJS的主要特点是 mvc 数据双向绑定 分模块 依赖注入    mvc m: $Scope 变量 V:视图 c:controllerfunction(){} 控制器 方法    Angularjs的用法 1.在一个有起始标签的元素开始标签内使用 ng-app来指定angularjs的作用范围 2.angularJS的表达式是双大括号 {{}} 里…...

    2024/5/7 4:24:48
  12. x265-1.8版本-x265.h代码注释

    注&#xff1a;问号以及未注释部分 会在x265-1.9版本内更新 /****************************************************************************** Copyright (C) 2013 x265 project** Authors: Steve Borho <steveborho.org>** This program is free software; you can …...

    2024/4/19 22:05:24
  13. angular6学习(九):数据绑定到事件

    实现功能&#xff1a;将html页面中文本框的输入的内容传递到ts文件&#xff0c;然后在html文件中显示ts文件中的这个内容。 html文件 一、绑定到事件 ts文件 显示结果&#xff1a; 二、双向绑定&#xff1a; html: app.module.ts...

    2024/4/20 20:07:11
  14. Angular数据绑定

    Angular的数据绑定分为三种&#xff1a; < h1> {{变量名}} </h1>&#xff1a;插值表达式&#xff08;单向绑定&#xff09;< img [src]"imgUrl"> :属性绑定<button (click)"toPrduct($event)">: 事件绑定($event是一个事件变量) …...

    2024/4/20 20:07:10
  15. Angular10 数据绑定

    Angular10数据绑定 中文官网地址 绑定方式 绑定类型语法分类举例插值、属性、attribute、css类、样式{{expression}}[target] expression’bind-target‘expression’单向从数据源到视图数据绑定{{title}}事件(target)statement’on-target‘statement’单向从视图到数据源的…...

    2024/4/20 20:07:09
  16. Angular如何给动态生成的元素绑定事件

    在AngularJS中&#xff0c;操作DOM一般在指令中完成&#xff0c;事件监听机制是在对于已经静态生成的dom绑定事件&#xff0c;而如果在指令中动态生成了DOM节点&#xff0c;动态生成的节点不会被JS事件监听。 举例来说&#xff1a; angular.module(myapp,[]) .directive(myText…...

    2024/4/21 3:26:16
  17. angular 组件间的双向绑定

    组件间的 双向绑定 child.component.ts ... Component({selector: app-child,template: childname-text:{{childName}}<br/><button (click)reset()>reset</button> })export class ChildComponent{Input() childName:string ;Output() childNameChange …...

    2024/4/21 3:26:15
  18. angular双向绑定—(按钮+下拉)

    checkbox绑定 游戏当中我已阅读勾选 <p><input type"checkbox" [(ngModel)]"sel">阅读并同意条款</p> <p><button [disabled]"!sel">登陆</button></p>export class AppComponent { selfalse;hobby…...

    2024/4/28 19:44:38
  19. angular双向绑定简单实现

    angular双向绑定简单实现 双向绑定原理 声明一个新组件时&#xff0c;将使用代理设计模式来代理每个属性&#xff08;getter和setter&#xff09;。因此&#xff0c;它将能够从代码和用户输入中检测属性值变化代理proxy&#xff1a; Proxy 可以理解成&#xff0c;在目标对象之前…...

    2024/4/29 2:31:09
  20. 【Angular6+】事件绑定

    Angular6 事件绑定 临近毕业开始了第二段实习&#xff0c;因为项目需求&#xff0c;技术栈从Vue转到Angular&#xff0c;才发现Angular已经到7了&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff0c;我两年前还是2来着&#xff0c;看来VAR&#xff08;Vu…...

    2024/4/29 0:10:58

最新文章

  1. 星戈瑞CY7-COOH荧光探针,助力生物医学研究

    CY7-COOH是一种近红外荧光染料&#xff0c;具有优异的光稳定性、高量子产率和强烈的荧光信号。此外&#xff0c;CY7-COOH还具有较长的激发和发射波长&#xff0c;使其在生物医学成像中具有较高的穿透力和较低的背景干扰。这使得CY7-COOH荧光探针在生物医学研究中具有诸多应用前…...

    2024/5/7 9:40:23
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/6 9:38:23
  3. 大数据学习十三天(hadhoop基础2)

    一: MapReduce概述(了解) MapReduce是hadoop三大组件之一,是分布式计算组件 Map阶段 : 将数据拆分到不同的服务器后执行Maptask任务,得到一个中间结果 Reduce阶段 : 将Maptask执行的结果进行汇总,按照Reducetask的计算 规则获得一个唯一的结果 我们在MapReduce计算框架的使用过…...

    2024/5/2 21:17:01
  4. macU盘在电脑上读不出来 u盘mac读不出来怎么办 macu盘不能写入

    对于Mac用户来说&#xff0c;使用U盘是很常见的操作&#xff0c;但有时候可能会遇到Mac电脑无法读取U盘的情况&#xff0c;这时候就需要使用一些特定的工具软件来帮助我们解决问题。本文就来告诉大家macU盘在电脑上读不出来是怎么回事&#xff0c;u盘mac读不出来怎么办。 一、m…...

    2024/5/6 6:41:57
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/7 5:50:09
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/6 9:21:00
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/6 21:42:42
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57