异步请求
JS中ajax原生请求
var xhr;
xhr=new XMLHttpRequest();
open('GET','url地址')
xhr.onreadyStateChange=function(){
if(xhr.readyState==4&&xhe.status==200){
console.log(xhr.responseText);
}
};
send();
封装后的ajax请求
GET
$.ajax({
type:'get',//不写默认get
url:'index.php'
data:{
name:'jim',
age:10
}//data中的数据也可以当作参数写在url后面
success:function(data){
console.log(data)
}
})
POST
$.ajax({
type:'post',
url:'',
data:{
name:'jim',
age:10
},
success:function(info){
console.log(info)
}
})
Vue中的axios请求
- Vue没有任何ajax请求方法
-
在vue1时代大家都用一个插件vue resource来发请求
- 支持promise
-
在Vue2.0时代,大家都用第三方库axios
- 支持promise
- 后来在HTML5时代,浏览器增加了一个特殊的异步请求,fetch,只在移动端使用
- 结合声明钩子获取数据
安装
npm install axios
引入
import axios from 'axios'
执行GET请求
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
}) //then promise语法,下面有具体描述
.catch(function (error) {
console.log(error);
});
// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});//catch 捕捉错误对象
POST请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
执行多个并发请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
可以通过axios传递相关配置来创建请求
axios(config)
//发送post请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
axios(url[, config])
// 发送 GET 请求(默认的方法)
axios('/user/12345');
异步操作
回调地狱
**以同时读取文件为例,因为是异步请求无法保证顺序,快慢取决于读取的文件大小.
无法保证顺序的代码*
var fs = require('fs')
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
})
fs.readFile('./data/b.txt', 'utf8', function (err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
})
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
})
通过回调嵌套的方式保证顺序
var fs = require('fs')
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
fs.readFile('./data/b.txt', 'utf8', function (err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
})
})
})
- 但是这样不停的嵌套很不好重复代码太多,反复的嵌套,最后形成回调地狱
- 所以在 EcmaScript 6 中新增了一个 API:Promise。
Promise 基本语法
var fs = require('fs')
// 在 EcmaScript 6 中新增了一个 API Promise
// Promise 是一个构造函数
// 创建 Promise 容器
// Promise 容器一旦创建,就开始执行里面的代码
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./data/aa.txt', 'utf8', function (err, data) {
if (err) {
// 失败了,承诺容器中的任务失败了
// console.log(err)
// 把容器的 Pending 状态变为 Rejected
// 调用 reject 就相当于调用了 then 方法的第二个参数函数
reject(err)
} else {
// 承诺容器中的任务成功了
// console.log(data)
// 把容器的 Pending 状态改为成功 Resolved
// 也就是说这里调用的 resolve 方法实际上就是 then 方法传递的那个 function
resolve(data)
}
})
})
// p1 就是那个承若
// 当 p1 成功了 然后(then) 做指定的操作
// then 方法接收的 function 就是容器中的 resolve 函数
p1
.then(function (data) {
console.log(data)
}, function (err) {
console.log('读取文件失败了', err)
})
综合以上封装刚才的readFile文件
var fs = require('fs')
function pReadFile(filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
pReadFile('./data/a.txt')
.then(function (data) {
console.log(data)
return pReadFile('./data/b.txt')
})
.then(function (data) {
console.log(data)
return pReadFile('./data/c.txt')
})
.then(function (data) {
console.log(data)
})
Generator函数的概念
Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)
function *gen(x){
var y=yied x+2;
return y;
}
- 上面的代码就是Generator函数,他是可以暂停的,所以函数名之前要加*加以区别;
- 整个Generator函数就是一个封装的异步任务,或者说是异步任务的容器,异步操作需要暂停的地方,都用yield语句注明.执行方法如下:
var g=gen(1);
g.next()//{value:3,done:fasle}
g.next()//{value:undefined,done:true} - 上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止。
- 换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。
Async/Awiat 配合promise使用
阅读本文前,期待您对上面promise以及ES6有所了解,会更容易理解。
本文以体验为主,不会深入说明.
第一个例子
- Async/Await应该是目前最简单的异步方案了
-
这里我们要实现一个暂停功能,输入N毫秒,则停顿N毫秒后才继续往下执行。
var sleep = function (time) {
return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, time); })
};
var start = async function () {
// 在这里使用起来就像同步代码那样直观 console.log('start'); await sleep(3000); console.log('end');
};
start();
控制台先输出start,稍等3秒后,输出了end。
基本规则
- async 表示这是一个async函数,await只能用在这个函数里面。
- await 表示在这里等待promise返回结果了,再继续执行。
- await 后面跟着的应该是一个promise对象(当然,其他返回值也没关系,只是会立即执行,不过那样就没有意义了…)
获得返回值
-
await等待的虽然是promise对象,但不必写.then(..),直接可以得到返回值。
var sleep = function (time) {
return new Promise(function (resolve, reject) { setTimeout(function () { // 返回 ‘ok’ resolve('ok'); }, time); })
};
var start = async function () {
let result = await sleep(3000); console.log(result); // 收到 ‘ok’
};
捕捉错误
-
既然.then(..)不用写了,那么.catch(..)也不用写,可以直接用标准的try catch语法捕捉错误。
var sleep = function (time) {
return new Promise(function (resolve, reject) { setTimeout(function () { // 模拟出错了,返回 ‘error’ reject('error'); }, time); })
};
var start = async function () {
try { console.log('start'); await sleep(3000); // 这里得到了一个返回错误 // 所以以下代码不会被执行了 console.log('end'); } catch (err) { console.log(err); // 这里捕捉到错误 `error` }
};
补充try catch
- try 语句允许我们定义在执行时进行错误测试的代码块。
- catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
-
JavaScript 语句 try 和 catch 是成对出现的。
try { //在这里运行代码 } catch(err) { //在这里处理错误 }
在这里我们故意在try中写错一个字,catch会捕捉到try中的错误,并执行代码处理它;
<!DOCTYPE html>
<html>
<head>
<script>
var txt="";
function message()
{
try
{
adddlert("Welcome guest!");
}
catch(err)
{
txt="There was an error on this page.\n\n";
txt+="Error description: " + err.message + "\n\n";
txt+="Click OK to continue.\n\n";
alert(txt);
}
}
</script>
</head>
<body>
<input type="button" value="View message" onclick="message()">
</body>
</html>
弹出窗为:
本页有一个错误.
错误描述:adddlert is not defined
点击确定继续
总的来说就是try里面放要运行的代码,catch里面放处理错误的代码;
补充throw
- 抛出异常
- 错误可以自定义
三者混合用:
<!DOCTYPE html>
<html>
<body>
<script>
function myFunction()
{
try
{
var x=document.getElementById("demo").value;
if(x=="") throw "值为空";
if(isNaN(x)) throw "不是数字";
if(x>10) throw "太大";
if(x<5) throw "太小";
}
catch(err)
{
var y=document.getElementById("mess");
y.innerHTML="错误:" + err + "。";
}
}
</script>
<h1>我的第一个 JavaScript 程序</h1>
<p>请输入 5 到 10 之间的数字:</p>
<input id="demo" type="text">
<button type="button" onclick="myFunction()">测试输入值</button>
<p id="mess"></p>
</body>
</html>
以上就是自己总结的,如有错误欢迎指出,时间太紧,没有太详细.主要还是当作自己的随笔笔记,总结为主.哈哈哈~