Ajax,跨域,nrm
一、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..'
})
});
输入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、什么是跨域
同源策略:
- 同源策略是浏览器的一种安全策略,所谓同源指的是请求URL地址中的协议、域名和端口都相同,只要其中之一不相同就是跨域
- 同源策略主要为了保证浏览器的安全性
- 在同源策略下,浏览器不允许Ajax跨域获取服务器数据
- 比如:
- http://api.baidu.com/deatil.html 域名不同
- https://api.baidu.com/deatil.html 协议不同
- http://api.baidu.com:8080/deatil.html 端口不同
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:
- https://github.com/Pana/nrm
- nrm can help you easy and fast switch between different npm registries....
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的更多相关文章
- Laravel中的ajax跨域请求
最近接触Laravel框架ajax跨域请求的过程中遇到一些问题,在这里做下总结. 一开始发起ajax请求一直报500错误,搜索相关资料后发现Laravel要允许跨域请求可以加入Cors中间件,代码如下 ...
- Ajax操作如何实现跨域请求 (JSONP和CORS实现Ajax跨域的原理)
由于浏览器存在同源策略机制,同源策略阻止ajax (XMLHttpRequest) 从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 特别的:由于同源策略是浏览器的限制,所以请求的发送和响 ...
- Ajax跨域问题的两种解决方法
浏览器不允许Ajax跨站请求,所以存在Ajax跨域问题,目前主要有两种办法解决. 1.在请求页面上使用Access-Control-Allow-Origin标头. 使用如下标头可以接受全部网站请求: ...
- 浅谈linux 下,利用Nginx服务器代理实现ajax跨域请求。
ajax跨域请求对于前端开发者几乎在任何一个项目中都会用到,众所周知,跨域请求有三种方式: jsonp; XHR2 代理: jsonp: 这种应该是开发中是使用的最多的,最常见的跨域请求方法,其实aj ...
- 解决ajax跨域请求 (总结)
ajax跨域请求,目前已用几种方法实现: 1)用原生js的xhr对象实现. var url="http://freegeoip.net/json/" ...
- Ajax跨域访问wcf服务中所遇到的问题总结。
工具说明:vs2012,sql server 2008R2 1.首先,通过vs2012建立一个wcf服务项目,建立好之后.再新开一个vs2012 建立web项目,通过jQuery的ajax方法访问服务 ...
- JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- Ajax跨域:Jsonp原理解析
推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...
- jquery ajax跨域调用
客户端: //ajax跨域调用的方法 $.ajax({ url:dustUrl+"/screenshot/getDevices.do", type: "get" ...
- 浅析JSONP-解决Ajax跨域访问问题
浅析JSONP-解决Ajax跨域访问问题 很久没有写随笔了,总是感觉没时间,其实时间就是...废话少说,前几天,工作上有一新需求,需要前端web页面异步调用后台的Webservice方法返回信息.实现 ...
随机推荐
- 在linux命令行利用SecureCRT上传下载文件
一般来说,linux服务器大多是通过ssh客户端来进行远程的登陆和管理的,使用ssh登陆linux主机以后,如何能够快速的和本地机器进行文件的交互呢,也就是上传和下载文件到服务器和本地?与ssh有关的 ...
- Redis学习笔记1 -- 单机环境时分布式锁的使用
使用第三方开源组件Jedis实现Redis客户端,且只考虑Redis服务端单机部署的场景. 前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKee ...
- 滴滴开源 Vue 组件库— cube-ui
cube-ui 是滴滴去年底开源的一款基于 Vue.js 2.0 的移动端组件库,主要核心目标是做到体验极致.灵活性强.易扩展以及提供良好的周边生态-后编译. 自 17 年 11 月开源至今已有 5 ...
- 无限滚动条的css布局理解
一.需求描述 做一个waymo的滚动条,在页面中显示两张图,一共4张图,无限滚动播放. .car{ width: 600px; height: 157px; margin: 100px auto; b ...
- windows 2003 安装 MVC 环境 404错误,无法找到该页
在windows server 2003 IIS6 系统安装 DotNet 4.0 + MVC3 环境后, .cshtml 文件依然无法运行,404错误 解决方案:查看处理程序隐射,如果没有.csht ...
- Codeforces Round #394 (Div. 2)
前一半是刚刚打完比赛的时候写的……不知为啥手腕有点僵,估计是前一个小时用力过度了吧= = 前四题看着还好,后两题就有点懵逼了……现在还不知道E题的题意到底是啥…… 不管了……还没找着官方题解,贴一下自 ...
- React Native之React速学教程(下)
概述 本篇为<React Native之React速学教程>的最后一篇.本篇将带着大家一起认识ES6,学习在开发中常用的一些ES6的新特性,以及ES6与ES5的区别,解决大家在学习Reac ...
- css3 animation运用
animation:mymove 5s infinite; @keyframes mymove { from {left:0px;} to {left:200px;} } @-webkit-keyfr ...
- Eclipse开发工具printf打印方法提示报错的解决方法
最近在学习java,在练习printf方法的使用时按照书上的语法配置却出现了报错.报错内容为:The method printf(String, Object[]) in the type Print ...
- 精准控制PWM脉冲的频率和数量
在一些项目中,我们经常要控制PWM脉冲的频率和数量,比如步进电机的控制等,下面分享一个程序是关于这方面的,程序的思想就是通过STM32的定时器来输出PWM波,并开启定时器中断,在中断里面计数脉冲的数量 ...