一、ajax 原理 和 使用

ajax,即在不重新加载整个网页的情况下,对网页的某部分进行更新。

下面演示ajax 的实现原理

配置:

cd ajax

参考:http://www.expressjs.com.cn/starter/generator.html

express --view=ejs myapp
cd myapp
npm install

1、完整的ajax流程:

(1)、 创建XMLHttpRequest对象

var xhr = new XMLHttpRequest();

(2)、准备发送

 xhr.open('get', './01check.js?username='+uname+'&password='+pw,true);

(3)、执行发送动作

 xhr.send(null);

(4)、监听response 回调函数

onreadystatechange 事件:每当 readyState 改变时,就会触发 onreadystatechange 事件。

2、代码逻辑

index.js 路由

......
router.get('/api/one',(req,res,next)=>{
res.json({
status:200,
result:'this is one.....'
})
}); /* GET home page. */
router.get('/one', function(req, res, next) {
res.render('index1', { title: 'Express' });
})
...........

index.ejs:

<body>
<button id="send">发送1个请求</button>
<script>
var btn = document.getElementById('send');
btn.addEventListener('click',function () {
// 使用原生的ajax 技术,发送一个网络请求
// 1.创建XMLHttpRequest对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} // 2.准备发送
/*
参数1: 请求方式 (get/post)
参数2: 请求url
参数3: 是否异步
*/
xhr.open('get','http://localhost:3000/api/one',true); // 3. 发送
xhr.send(); // 4. 监听服务器的响应
// 一旦服务器响应回来之后, 就会执行这个函数
xhr.onreadystatechange = function () {
console.log(xhr.readyState);
if(xhr.readyState === 4){ // 代表服务器已经给了响应, 不代表响应成功
if(xhr.status === 200){
console.log(xhr.response);
}
}
} });
</script>
</body> // 结果:
/*
2
3
4
{"status":200,"result":"this is one....."}
*/


index.js 路由:

router.get('/api/two',(req,res,next)=>{
console.log(req.query);
res.json({
status:200,
result:'this is two.....'
})
}); router.get('/two', function(req, res, next) {
res.render('index2', { title: 'Express' });
});

index2.ejs

<body>
<input id="account" type="text" name="account">
<input id="pwd" type="text" name="pwd">
<button id="send">发送一个请求</button>
<script>
window.onload=function () { var btn = document.getElementById('send');
btn.onclick = function () {
// 使用原生的ajax 技术,发送一个网络请求
// 1.创建XMLHttpRequest对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} // 从页面获取需要传递的数据
var userName = document.getElementById('account').value;
var pwd = document.getElementById('pwd').value; // 2.准备发送
/*
参数1: 请求方式 (get/post)
参数2: 请求url
参数3: 是否异步
*/
// 后面跟一个随机数值,保证每次发送ajax请求,都是真的发然后从响应中获取最新数据,而不是从缓存中取得
xhr.open('get', 'http://localhost:3000/api/two?account=' + account + '&pwd=' + pwd + '&random=' + getRandomStr(), true); // 3. 发送
xhr.send(); // 4. 监听服务器的响应
// 一旦服务器响应回来之后, 就会执行这个函数
xhr.onreadystatechange = function () {
// 5. 处理响应的数据 (对方说话)
console.log(xhr.readyState);
if(xhr.readyState === 4){ // 代表服务器已经给了响应, 不代表响应成功
if(xhr.status === 200){
console.log(xhr.response);
}
}
}
}
} function getRandomStr() {
return Math.random() + (new Date().getTime())
}
</script> </body>

前端打印:

2
3
4
{"status":200,"result":"this is two....."}

服务端打印:

{ account: '[object HTMLInputElement]',
pwd: '123456',
random: '1547356096169.2708' }
GET /api/two?account=[object%20HTMLInputElement]&pwd=123456&random=1547356096169.2708 200 8.824 ms - 42


封装ajax:

AjaxTool.js:

(function (window) {
function AjaxTool() {} AjaxTool.ajaxRequest = function (url, paramObj, timeout, successCallBack, errorCallBack) {
// 1.创建XMLHttpRequest对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} // 2.准备发送
/*
参数1: 请求方式 (get/post)
参数2: 请求url
参数3: 是否异步
*/
// 后面跟一个随机数值,保证每次发送ajax请求,都是真的发然后从响应中获取最新数据,而不是从缓存中取得
var params_str = getStrWithObj(paramObj);
var uri_str = url + '?' + params_str;
// 转码
var codeURI = encodeURI(uri_str)
xhr.open('get', codeURI, true); // 3. 发送
xhr.send(); // 4. 监听服务器的响应
xhr.onreadystatechange = function () {
// 5. 处理响应的数据
console.log(xhr.readyState);
if(xhr.readyState === 4){ // 代表服务器已经给了响应, 不代表响应成功
if(xhr.status === 200){
successCallBack(xhr);
}else {
errorCallBack(); }
}
} // 5. 控制请求的时间
var timer;
if(timeout > 0){
timer = setTimeout(function () {
// 取消ajax 请求
xhr.abort();
},timeout);
} }
/*
* 把对象转换成字符串
* */
function getStrWithObj(paramsObj) {
var arr = [];
for(var k in paramsObj){
var str = k + '=' + paramsObj[k];
arr.push(str);
}
arr.push('random='+ getRandomStr());
return arr.join('&');
} /*
返回一个随机数
* */
function getRandomStr() {
return Math.random() + (new Date().getTime())
} window.AjaxTool = AjaxTool;
})(window);

index3.ejs:

<body>
<input id="account" type="text" name="account">
<input id="pwd" type="text" name="pwd">
<button id="send">发送一个请求</button>
<script>
window.onload=function () { var btn = document.getElementById('send');
btn.onclick = function () {
// 使用原生的ajax 技术,发送一个网络请求
// 1.创建XMLHttpRequest对象
var xhr;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} // 从页面获取需要传递的数据
var userName = document.getElementById('account').value;
var pwd = document.getElementById('pwd').value; // 2.准备发送
/*
参数1: 请求方式 (get/post)
参数2: 请求url
参数3: 是否异步
*/
// 后面跟一个随机数值,保证每次发送ajax请求,都是真的发然后从响应中获取最新数据,而不是从缓存中取得
xhr.open('get', 'http://localhost:3000/api/two?account=' + account + '&pwd=' + pwd + '&random=' + getRandomStr(), true); // 3. 发送
xhr.send(); // 4. 监听服务器的响应
// 一旦服务器响应回来之后, 就会执行这个函数
xhr.onreadystatechange = function () {
// 5. 处理响应的数据 (对方说话)
console.log(xhr.readyState);
if(xhr.readyState === 4){ // 代表服务器已经给了响应, 不代表响应成功
if(xhr.status === 200){
console.log(xhr.response);
}
}
}
}
} function getRandomStr() {
return Math.random() + (new Date().getTime())
}
</script> </body>

3、简单版原生 post方式

<body>
<input id="account" type="text" name="account">
<input id="pwd" type="text" name="pwd">
<button id="send">发送一个请求</button>
<script>
window.onload=function () {
var btn = document.getElementById('send');
btn.onclick = function () {
// 1. 获取数据
var account = document.getElementById('account').value;
var pwd = document.getElementById('pwd').value; // 第一步
var xhr = new XMLHttpRequest();
// 第二步
xhr.open('post','http://localhost:3000/api/four',true)
// 第三步
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send('account='+account + '&pwd=' + pwd); // 第四步
xhr.onreadystatechange = function () {
console.log(xhr.readyState);
console.log(xhr.status);
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText);
}else {
console.log('请求失败');
}
} }
} </script> </body>

4、ajax 完整封装

(function(window){
function AjaxTool(){}
AjaxTool.ajaxRequest = function(params,successCallBack,errorCallBack){
// 0. 获取参数
var requestType = params['requestType'] || 'get';
var url = params['url'];
var paramsObj = params['paramsObj'];
var timeout = params['timeout'];
console.log(params);
// 1.创建XMLHttpRequest对象 (找到一个电话)
var xhr;
if(window.XMLHttpRequest){
xhr =new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
} // 2.判断请求方式
if(requestType.toLowerCase() === 'get'){
var codeURI = encodeURI(url + '?' + getStrWithObject(paramsObj));
xhr.open('get',codeURI,true);
xhr.send();
}else if(requestType.toLowerCase() === 'post'){
// 请求体
var codeParam = encodeURI(getStrWithObject(paramsObj));
xhr.open('post',url,true);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
console.log(codeParam);
xhr.send(codeParam); } // 3. 监听服务器响应
xhr.onreadystatechange = function(){
// 3.1 处理响应数据
if(xhr.readyState === 4){
// 4 代表服务器给响应了,并不代表响应成功
if(xhr.status === 200){
successCallBack(xhr);
// 清除定时器
clearTimeout(timer);
}else{
errorCallBack();
}
}
} // 4. 控制响应时间
var timer;
if(timeout > 0){
timer = setTimeout(function(){
// 取消ajax请求
xhr.abort();
},timeout);
} } /*
返回一个随机数
*/
function getRandomStr(){
return Math.random() + (new Date().getTime());
} /*
把对象转成字符串
*/
function getStrWithObject(paramsObj){
var arr = [];
for(var key in paramsObj){
var str = key + '=' + paramsObj[key];
arr.push(str)
}
arr.push('random=' + getRandomStr())
return arr.join('&');
}
window.AjaxTool = AjaxTool;
})(window)

index5.ejs:

<body>
<input id="account" type="text" name="account">
<input id="pwd" type="text" name="pwd">
<button id="send">发送一个请求</button>
<script src="../js/AjaxTool.js"></script>
<script>
window.onload=function () {
var btn = document.getElementById('send');
btn.onclick = function () {
// 1. 获取数据
var account = document.getElementById('account').value;
var pwd = document.getElementById('pwd').value; // 2. 处理数据
var paramsObj = {
'account':account,
'pwd':pwd
} var params = {
'requestType':'post',
'url':'http://localhost:3000/api/five',
'paramsObj':paramsObj,
'timeout':2000
} AjaxTool.ajaxRequest(params,function (xhr) {
console.log('成功' + xhr.responseText);
},function () {
console.log('失败');
}); }
} </script> </body>

index.js 服务端路由文件:

router.get('/five',(req,res,next)=>{
res.render('index5')
}); router.post('/api/five',(req,res,next)=>{
console.log(req.body);
res.json({
status:200,
result:'this is five...method:post..'
})
});

访问:http://localhost:3000/five

输入admin 123456 ,然后提交

前端打印:成功{"status":200,"result":"this is five...method:post.."}

服务端打印:{ account: 'admin', pwd: '123123', random: '1547522571613.208' }

5、用 jquery 进行 ajax 请求

三方封装的是最完善的,我们用三方封装好的即可,但是对ajax原生的执行的大致逻辑知道一些比较好。

index6.ejs:

<body>
<form action="http://localhost:3000/api/six" method="post">
<input id="account" type="text" name="account">
<input id="pwd" type="text" name="pwd">
<input id="send" type="submit" value="请求">
</form>
<script src="/js/jquery.js"></script>
<script>
$('form').on('submit', function () {
console.log($(this).serialize()); //account=admin&pwd=123456
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
data: $(this).serialize(),
success: function (data) {
console.log(data); //{status: 200, result: "this is six...."}
}
}); // 阻止默认事件
return false;
});
</script>

服务端:

router.post('/api/six',(req,res,next)=>{
console.log(req.body);
res.json({
status:200,
result:'this is six....'
})
});

二、跨域

1、什么是跨域

同源策略:

2、解决方案:

jsonp
document.domain+iframe :只有主域名相同的情况下方可使用此方法
location.hash + iframe
window.name + iframe
window.postMessage
flash等第三方插件

3、跨域演示

express-generator 快速创建一个应用的骨架server,然后在服务端index.js 路由中

router.get('/', function(req, res, next) {
// res.render('index', { title: 'Express' });
console.log(`收到客户端的请求: ${req.url}`);
res.end('end');
});

在本地新创建一个页面,不要通过和 server 端口一致

<body>
<button id="send">点我</button>
<script src="js/AjaxTool.js"></script>
<script>
window.onload = function () {
var btn = document.getElementById('send');
btn.onclick = function () {
var paramObj = {
'name':'zhangsan',
'pwd':'123'
};
var params = {
'requestType' : 'get',
'url' : 'http://localhost:3000/',
'paramObj' : paramObj,
timeout : 2000
}; // 发起请求
AjaxTool.ajaxRequest(params,function (xhr) {
console.log('success...'+ xhr.responseText);
},function () {
console.log('failed.....');
})
}
}
</script> </body>

结果:

服务端还是收到请求了,打印:

收到客户端的请求: /?name=zhangsan&pwd=123&random=1547690599507.3115

GET /?name=zhangsan&pwd=123&random=1547690599507.3115 - - ms - -

客户端打印如下图:

4、jsonp 解决跨域问题

  • jsonp跨域必须前后端联合支持

  • jsonp只支持get不支持post

(1) 演示1

路由:

router.get('/',function (req,res,next) {
console.log(`收到客户端的请求: ${req.url}`);
var data = JSON.stringify({
status_code:200,
result:{
name:'张三',
age:19,
friend:['李四','王五','赵六']
}
});
res.end('getData('+data+')');
});

前端页面:

<body>
<script>
function getData(data) {
console.log(data);
}
</script>
<script src="http://localhost:3000/"></script>
</body>

通过 script 引入,来跨域请求,这个是可行的,同样的方式,还有 css标签的引入

(2) 封装

路由:

router.get('/',function (req,res,next) {
console.log(`收到客户端的请求: ${req.url}`);
var data = JSON.stringify({
status_code:200,
result:{
name:'张三',
age:19,
friend:['李四','王五','赵六']
}
});
console.log(`${req.query.callback}(${data})`);
res.end(`${req.query.callback}(${data})`);
});

前端:

<body>
<script> jsonp({
url: 'http://localhost:3000/',
data: '',
success: function (data) {
console.log(11111);
console.log(data);
}
});
jsonp({
url: 'http://localhost:3000/',
data: '',
success: function (data) {
console.log(22222); console.log(data);
}
}); /*
* 1、让函数名称不一致
* 2、调用完成后删除
* */
function jsonp(option) {
// 1. 将用户通过对象的命名空间传递进来的函数 挂载到全局
var callbackName = 'hello_' + Math.random().toString().substr(2);
window[callbackName] = function (data) {
option.success(data);
// 删除 script 标签 ,多次调用后 script 太多了,在这里删除掉
document.body.removeChild(script);
}; // 1. 处理url的拼接
option.url = option.url + '?callback=' + callbackName;
// 2. 创建script标签
var script = document.createElement('script');
script.src = option.url;
document.body.appendChild(script); /*说明: 拼接完url后,url 会带上函数的名称,服务端根据url 取得函数名称,然后返回的时候
res.end(`${req.query.callback}(${data})`);
* */
} </script>
</body>

前端代码注释:

加断点可以查看执行流程,首先 jsonp({})执行,接着到下面的 function jsonp({}),在下面的 function jsonp() 里面, window[callbackName] = function (data) {} ,在这里只是声明了函数,并且是全局的,但是并没有调用,里面的东西是在后来服务端 响应后调用的,并接着调用 了 里面的 option.success(data) 的函数,因为这个时候,服务端返回的时候把参数data 也传回来了 res.end(${req.query.callback}(${data})); 。所以接着执行了上面的 jsonp({}) 里面的 success:function(){data} 的函数。

执行结果:

三、nrm

什么是nrm:

install:

$ npm install -g nrm

查看有哪些源:

$ nrm ls

* npm -----  https://registry.npmjs.org/
cnpm ---- http://r.cnpmjs.org/
taobao -- https://registry.npm.taobao.org/
nj ------ https://registry.nodejitsu.com/
rednpm -- http://registry.mirror.cqupt.edu.cn
skimdb -- https://skimdb.npmjs.com/registry

选择镜像源:

$ nrm use cnpm  //switch registry to cnpm

    Registry has been set to: http://r.cnpmjs.org/

注意:每次安装包的时候,依然是使用 npm 命令来安装。

Ajax,跨域,nrm的更多相关文章

  1. Laravel中的ajax跨域请求

    最近接触Laravel框架ajax跨域请求的过程中遇到一些问题,在这里做下总结. 一开始发起ajax请求一直报500错误,搜索相关资料后发现Laravel要允许跨域请求可以加入Cors中间件,代码如下 ...

  2. Ajax操作如何实现跨域请求 (JSONP和CORS实现Ajax跨域的原理)

    由于浏览器存在同源策略机制,同源策略阻止ajax (XMLHttpRequest) 从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 特别的:由于同源策略是浏览器的限制,所以请求的发送和响 ...

  3. Ajax跨域问题的两种解决方法

    浏览器不允许Ajax跨站请求,所以存在Ajax跨域问题,目前主要有两种办法解决. 1.在请求页面上使用Access-Control-Allow-Origin标头. 使用如下标头可以接受全部网站请求: ...

  4. 浅谈linux 下,利用Nginx服务器代理实现ajax跨域请求。

    ajax跨域请求对于前端开发者几乎在任何一个项目中都会用到,众所周知,跨域请求有三种方式: jsonp; XHR2 代理: jsonp: 这种应该是开发中是使用的最多的,最常见的跨域请求方法,其实aj ...

  5. 解决ajax跨域请求 (总结)

    ajax跨域请求,目前已用几种方法实现:   1)用原生js的xhr对象实现.                var url="http://freegeoip.net/json/" ...

  6. Ajax跨域访问wcf服务中所遇到的问题总结。

    工具说明:vs2012,sql server 2008R2 1.首先,通过vs2012建立一个wcf服务项目,建立好之后.再新开一个vs2012 建立web项目,通过jQuery的ajax方法访问服务 ...

  7. JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  8. Ajax跨域:Jsonp原理解析

    推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...

  9. jquery ajax跨域调用

    客户端: //ajax跨域调用的方法 $.ajax({ url:dustUrl+"/screenshot/getDevices.do", type: "get" ...

  10. 浅析JSONP-解决Ajax跨域访问问题

    浅析JSONP-解决Ajax跨域访问问题 很久没有写随笔了,总是感觉没时间,其实时间就是...废话少说,前几天,工作上有一新需求,需要前端web页面异步调用后台的Webservice方法返回信息.实现 ...

随机推荐

  1. JQuery的一些基础知识

    JQuery的核心的一些方法 each(callback) '就像循环$("Element").length; ‘元素的个数,是个属性$("Element"). ...

  2. sql server or Oracle: table MS_Description

    --SQL Server表描述 及 字段描述的增.删.改.查询 --sql server 2000系统表sysproperties在SQL 2008中无效的问题 今天无意中在网上发现Sqlserver ...

  3. python3在anaconda下安装caffe失败

    Python 跟 Python3 完全就是两种语言 0x00 import caffe FAILED 环境为 Ubuntu 16 cuda 8.0 NVIDIA 361.77 Anaconda2.昨天 ...

  4. Java jsp 自定义标签

    1 自定义标签 1.1 引入 需求: 向浏览器输出当前客户的IP地址 (只能使用jsp标签) 1.2 第一个自定义标签开发步骤 1)编写一个普通的java类,继承SimpleTagSupport类,叫 ...

  5. WPF中使用定时器 DispatcherTimer 做TCP连接中的心跳 HeartBeat

    开发过程中经常遇到定时触发的需求,如:TCP/IP连接中,使用心跳包保持连接或检测连接是否已经中断. WPF中有多种定时器: 1.using System.Windows.Threading; 代码如 ...

  6. Codeforces Round #415 (Div. 2) B. Summer sell-off

    B. Summer sell-off time limit per test   1 second memory limit per test   256 megabytes   Summer hol ...

  7. 常用APDU指令错误码

    状态码 性质 错误解释 9000 正常 成功执行 6200 警告 信息未提供 6281 警告 回送数据可能出错 6282 警告 文件长度小于Le 6283 警告 选中的文件无效 6284 警告 FCI ...

  8. js 显示 base64编码 的二进制流 图片

    Data URI scheme.Data URI scheme是在RFC2397中定义的,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入.比如上面那串字符,其实是一张小图片,将这些字 ...

  9. C++:关于委托类

    转自:http://blog.csdn.net/dadalan/article/details/4041931.vs2010已经支持function/bind,能很好实现委托. [说明] 本文不仅介绍 ...

  10. selenium层级定位及鼠标键盘操作

    #code:utf-8 from selenium import webdriver from selenium.webdriver.common.action_chains import Actio ...