目录
一、定义
Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件。ES6统一了用法,并原生提供了Promise对象。作为对象,Promise有一下两个特点:
- 对象的状态不受外界影响。
Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
2.一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态。
Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
Promise 优缺点
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
二、三种状态
Pending状态(进行中)、Fulfilled状态(已成功)、 Rejected状态(已失败)
一旦发生改变就只有一种状态:Pending -> Fulfilled Pending -> Rejected。
三、基本用法
Resolve,用来接收完成状态,
reject用来接收失败的状态。
//Promise 通过new关键词 回调函数有两个形参 第一个:resolve(成功) reject(失败的方法)
//resolve reject这两个可以改变Promise实例的状态
let promise=new Promise(function(resolve,reject){
let flag=true;
if(flag){
resolve('成功');
}else{
reject('失败');
}
})
//获取 Promise的值,有两个参数,第一个参数:回调函数显示成功的状态,第二个是显示失败的状态
promise.then(resolve=>console.log(resolve),
reject=>console.log(reject)
)
说明:then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。这两个函数都是可选的,不一定要提供。它们都接受Promise对象传出的值作为参数。
四、模拟异步
案例:
function timeout(ms){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(ms+'秒后打印');
},ms)
})
}
console.log(1);
setTimeout(()=>{
console.log('1秒后打印');
},0);
console.log(2);
打印顺序为什么不是打印出 1 后不是接着打印setTimeout函数,而是直接打印下面的2?
console.log(1);
console.log(2);
setTimeout(()=>{
console.log('1秒后打印');
},0);
其结果与之前一样,与代码的顺序无关
setTimeout 只是在模拟异步,其代码运行到它时还是单线程运行,不是多线程;在运行代码时,把 setTimeout 下调了,调至2 后面,代码顺序如上面灰色块里的代码顺序,在其他代码执行完后执行,与变量上提原理一样。
示例:多少s后打印一句话
function timeout(ms){
console.log(2);
return new Promise((resolve,reject)=>{
console.log(3);
setTimeout(()=>{
console.log(6);
console.log(ms+'秒后打印');
resolve('end');
},ms)
})
}
console.log(1);
const mypromise=timeout(2000);
console.log(4);
mypromise.then((resolve)=>{
console.log(resolve);
})
console.log(5);
五、执行步骤
function timeout(ms){
console.log(2);
return new Promise(function(relove,reject){
setTimeout(()=>{
console.log(3);
relove(4);
},ms);
})
}
console.log(1);
let res = timeout(3000);
res.then(relove=>console.log(relove))
说明:Promise 新建后立即执行,所以首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以4最后输出。
六、json对象数据格式
1. 什么是 JSON?
- JSON 英文全称 JavaScript Object Notation
- JSON 是一种轻量级的数据交换格式。
- JSON是独立的语言 *
- JSON 易于理解。
2. JSON 语法规则
- 数据为 键/值 对。
- 数据由逗号分隔。
- 大括号保存对象
- 方括号保存数组
3. JSON 对象
JSON 对象保存在大括号内。
就像在 JavaScript 中, 对象可以保存多个 键/值 对:
{"name":"Runoob", "url":"www.runoob.com"}
4. JSON 数组
JSON 数组保存在中括号内。
就像在 JavaScript 中, 数组可以包含对象:
"sites":[ {"name":"Runoob", "url":"www.runoob.com"},
{"name":"Google", "url":"www.google.com"},
{"name":"Taobao", "url":"www.taobao.com"}
]
在以上实例中,对象 "sites" 是一个数组,包含了三个对象。
每个对象为站点的信息(网站名和网站地址)。
5. 相关函数
函数 | 描述 |
---|---|
JSON.parse() | 用于将一个 JSON 字符串转换为 JavaScript 对象。 |
JSON.stringify() | 用于将 JavaScript 值转换为 JSON 字符串。 |
6. 示例
var Person='{"realname":"张三","age":19}';
const P1=JSON.parse(Person);
console.log(P1.realname); //张三
var persons='["张三","李四"]';
const p1=JSON.parse(persons);
console.log(p1); //["张三", "李四"]
var P2={realname:'张三',age:19};
console.log(JSON.stringify(P2)); //{"realname":"张三","age":19}
七、封装ajax
1. 什么是ajax
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
2. ajax的工作原理
- 创建 XMLHttpRequest 对象
- 向服务器发送请求
- 服务器响应
2.1、创建 XMLHttpRequest 对象
XMLHttpRequest 是 AJAX 的基础。
所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。
创建 XMLHttpRequest 对象的语法:const ajax=new XMLHttpRequest();
老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象:
const ajax=new ActiveXObject("Microsoft.XMLHTTP");
为了应对所有的现代浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,则创建 XMLHttpRequest 对象。如果不支持,则创建 ActiveXObject
2.2、向服务器发送
XMLHttpRequest 对象用于和服务器交换数据
如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法:
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
方法 | 描述 |
---|---|
open(method,url,async) | 规定请求的类型、URL 以及是否异步处理请求。
|
send(string) | 将请求发送到服务器。
|
GET 还是 POST?
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
然而,在以下情况中,请使用 POST 请求:
- 不愿使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST 没有数据量限制)
- 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
异步 - True 或 False?
AJAX 指的是异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。
XMLHttpRequest 对象如果要用于 AJAX 的话,其 open() 方法的 async 参数必须设置为 true
对于 web 开发人员来说,发送异步请求是一个巨大的进步。很多在服务器执行的任务都相当费时。AJAX 出现之前,这可能会引起应用程序挂起或停止。
通过 AJAX,JavaScript 无需等待服务器的响应,而是:
- 在等待服务器响应时执行其他脚本
- 当响应就绪后对响应进行处理
2.3、 服务器响应
onreadystatechange 事件
当请求被发送到服务器时,我们需要执行一些基于响应的任务。
每当 readyState 改变时,就会触发 onreadystatechange 事件。
readyState 属性存有 XMLHttpRequest 的状态信息。
在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。
当 readyState 等于 4 且状态为 200 时,表示响应已就绪
使用回调函数
回调函数是一种以参数形式传递给另一个函数的函数。
如果您的网站上存在多个 AJAX 任务,那么您应该为创建 XMLHttpRequest 对象编写一个标准的函数,并为每个 AJAX 任务调用该函数。
该函数调用应该包含 URL 以及发生 onreadystatechange 事件时执行的任务(每次调用可能不尽相同)
3. 示例
ajax.html文件
const ajax=new XMLHttpRequest();
//console.log(ajax.readyState); //0
//1:用get打开请求地址
ajax.open("GET","http://127.0.0.1:5500/test.json");
//console.log(ajax.readyState); //1
2:发送请求
ajax.send();
//console.log(ajax.readyState); //1
ajax.onreadystatechange=()=>{
if(ajax.readyState == 4){//xml的状态
//console.log('服务请求完成');
if(ajax.status==200){//代表成功
const data=JSON.parse(ajax.response);
console.log(data);
}else{
console.log("请求失败");
}
}
}
test,json文件
{
"code":"200",
"message":"人员列表信息",
"lists":[
{
"name":"张三1",
"sex":"男",
"age":"30"
},
{
"name":"小红",
"sex":"女",
"age":"22"
}
]
}
在运行过程中出现的问题--关于获取 test,json文件的路径
在获取浏览器窗口的路径时,要注意跨域问题。
用 Open In Default Browser 打开,可获取的路径是错误的
file:///C:/Users/28411/Desktop/lesson-practice/Ajax.html
用 Open with Live Server 打开所获得的路径才是正确的
此获得的路径在你的 test,json文件 和 ajax.html文件 在同一文件夹下时可以直接修改路径后缀Ajax.html
用promise封装
function sendajax(url){
return new Promise((resolve,reject)=>{
const Obj = new XMLHttpRequest();
Obj.open("GET",url);
Obj.send();
Obj.onreadystatechange = ()=>{
if(Obj.readyState==4){
if(Obj.status==200){//http状态码
const data = JSON.parse(Obj.response);
resolve(data);
}else{
reject("数据请求失败...");
}
}
}
})
}
const MyPromise = sendajax("http://127.0.0.1:5500/test.json");
MyPromise.then((resolve)=>{
console.log(resolve);
})
八、 Proimse.prototype.then
Promise 实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,参数可选。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。根据这一特性我们可以采用链式
function demo(){
return new Promise((resolve)=>{
resolve('hello');
})
}
let Mydemo=demo();
Mydemo.then((resolve)=>{
console.log(resolve); //hello
return resolve+'2';
}).then((resolve)=>{
console.log(resolve); //hello2
})
九、 Promise.prototype.catch()
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。
Promise 对象的错误具有"冒泡"性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个 catch 语句捕获。
function demo(){
return new Promise((resolve,reject)=>{
resolve('hello');
})
}
let Mydemo=demo();
Mydemo.catch((reject)=>{
console.log(reject);
})
只有在 发生错误时才能捕获到