Promise和async和await的理解
1.回调函数直接作为函数参数
1.1传统的方式,使用jquery的get方法
语法
$.get(URL,data,function(data,status,xhr),dataType)
该方法里面可以设置回调函数,如下代码,可以在console窗口中直接执行,function(data)就代表get调用/数据请求之后的回调函数
$.get('/')
//{readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
$.get('/',function(data){console.log(data.length)})
//{readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
//208896
$.get('/',function(data2){console.log(data2.length)})
//{readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
//206281
$.get('/',function(){console.log("a")})
//{readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
//a
1.2 fetch方法
请注意,fetch
规范与 jQuery.ajax()
主要有三种方式的不同:
- 当接收到一个代表错误的 HTTP 状态码时,从
fetch()
返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的ok
属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。 fetch()
不会接受跨域 cookies;你也不能使用fetch()
建立起跨域会话。其他网站的Set-Cookie
头部字段将会被无视。fetch
不会发送 cookies。除非你使用了credentials 的初始化选项。(自 2017 年 8 月 25 日以后,默认的 credentials 政策变更为same-origin
。Firefox 也在 61.0b13 版本中进行了修改)
fetch('./')
//Promise {<pending>}
$.get('/',function(data){console.log(data.length)})
//{readyState: 1, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
//208896
fetch('./').then(res=>res.text()).then(data=>console.log(data.length))
//Promise {<pending>}
//206267
1.1 的jquery是将回调函数作为一个参数传递,而fetch里面是利用promise的then方法来调用回调函数。
1.3 Promise方法
setTimeout(console.log(123),1000)
//123
new Promise((resolve,reject)=>{
setTimeout(function(){resolve(123)},1000)
}).then(res=>console.log(res))
//Promise {<pending>}
//间隔1s后,123
new Promise((resolve,reject)=>{
setTimeout(function(){reject(123)},1000)
}).then(res=>console.log(res))
//Promise {<pending>}
//Uncaught (in promise) 123
new Promise((resolve,reject)=>{
setTimeout(function(){reject(123)},1000)
}).then(res=>console.log(res))
.catch(e=>console.log(e))
//Promise {<pending>}
//123
new Promise的时候里面内容会立即执行!!因而为了能实现调用时执行,Promise一般都是作为函数的返回值,可以将普通的回调函数作为参数的形式改造成promise的形式,和执行如果setTimeout的效果是一样的。promise返回的是reject,就会抛异常,一般reject的通过catch来捕获异常。
接下来定义一个函数p1,该函数返回Promise对象,执行该函数就会返回一个Promise对象。
var p1=()=>new Promise((resolve,reject)=>{
setTimeout(function(){resolve(12345)},1000)
})
p1
//()=>new Promise((resolve,reject)=>{
// setTimeout(function(){resolve(12345)},1000)
// })
p1()
//Promise {<pending>}
await会拿到resolve结果,是then函数的语法糖,如下代码,async+await是promise+then的语法糖。
async function q1(){
var res=await p1();
console.log(res);
}
q1()
//12345
function q1(){
p1().then(res=>console.log(res));
}
q1()
//12345
思考一下下面的代码,最后会同时打印出12345。
var p1=()=>new Promise((resolve,reject)=>{
setTimeout(function(){resolve(12345)},1000)
})
async function q2(){
var res=await p1();
console.log(res);
}
async function q1(){
var res=await p1();
console.log(res);
}
q1();
q2();
//Promise {<pending>}
//12345
//12345
2.async和await的理解
async函数(异步函数)
函数的返回值为promise对象
promise对象的结果由aync函数的返回值决定。
await表达式
await操作符用于等待一个Promise对象。他只能在async function中使用
await得到的结果就是Promise成功的value
async function fn() {
return 1;
}
const result = fn();
console.log(result);
async function fn1() {
throw 2;
}
const result1 = fn1();
console.log(result1);
代码运行结果为,可以看出async函数的结果值为Promise对象
Promise {
: 1}
proto__: Promise
[[PromiseStatus]]*: "resolved"
[[PromiseValue]]*: 1
Promise {: 2}
- proto: Promise
- [[PromiseStatus]]: "rejected"
- [[PromiseValue]]: 2
从代码运行结果可以看出,async函数的返回值是Promise对象,拿到这个对象之后我们就可以调用then函数了,调用这个then的回调函数,
async function fn1() {
throw 2;
}
const result1 = fn1();
console.log(result1);
result1.then(
value => {
console.log("onResolved()", value);
},
reason => {
console.log("onRejected()", reason)
}
)
代码运行结果为:
Promise {<rejected>: 2}
index.js:19706 onRejected() 2
async函数的返回其实是这样的
async function fn1() {
return Promise.resolve(2);
// return Promise.reject(3);
}
上面的代码可以发现async函数的返回结果是Promise对象,这个Promise对象的结果必须通过调用then函数才能取出来。如果我们不想通过调用then函数来处理得到value值呢?
这里注意一点await在的函数一定要声明为async函数,不然会报错,如下代码,fs()函数如果没有被定义为async函数,则会报错,这样我们直接通过await就拿到了async函数返回的值。
async function fn2() {
return 1;
}
async function f3() {
const value=await fn2();
console.log(value);
}
f3();
如果await右侧表达式不是promise,得到的结果就是它本身。
async function f4() {
const value=await 11;
console.log(value);
}
f4();
//11
上面的例子await得到的都是成功的结果,如果想得到失败的结果呢??用try catch来进行,如下代码
async function fn2() {
return Promise.reject('ed');
}
async function f4() {
try {
const value = await fn2();
} catch (error) {
console.log(error);
}
}
f4();
//ed