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