Promise和async和await的理解

Posted zdjblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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}

  1. proto__: Promise

  2. [[PromiseStatus]]*: "resolved"

  3. [[PromiseValue]]*: 1

  4. Promise {: 2}

    1. proto: Promise
    2. [[PromiseStatus]]: "rejected"
    3. [[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

以上是关于Promise和async和await的理解的主要内容,如果未能解决你的问题,请参考以下文章

async/await 和promise的理解

理解异步之美:Promise与async await

promise与async和await的区别

[ECMAScript] 说说你对async/await的理解?

node.js异步控制流程 回调,事件,promise和async/await

Async/Await替代Promise的理由