ES7 async/await

ES7引入的async/await在JavaScript异步编程中是一个很好的改进,它提供了使用同步样式的代码异步访问resources资源的方式,而且不会阻塞线程。

  • async/await用于编写JavaScript异步程序
  • async/await代码书写方式和同步编程相似,代码简洁易读。
  • async/await基于Promise
  • async/await中可使用try-catch捕获异常

async

  • async函数

async函数返回的是一个Promise对象,async函数包括函数语句、函数表达式、Lambda表达式。

async函数会返回一个Promise对象,如果在async函数中return一个直接量,async会将这个直接量通过Promise.resolve()封装成Promise对象。

async function fn(){
    return 1;
}
console.log(fn());//Promise {: 1}
4933701-71eae9a31fe951fd.png
image.png

async函数调用时会返回Promise对象,Promise对象拥有status和value。如果async函数拥有返回值,当调用async函数时,函数内部会调用Promise.resolve()方法将其转化为一个Promise对象并作为返回。

如果async函数没有返回值,则会返回Promise.resolve(undefined)。

async function fn(){
}
console.log(fn());//Promise {: undefined}
4933701-ef1c141aba476de3.png
image.png

async函数调用时函数内部如果抛出错误则出现错误

async function fn(){
    throw new Error("rejected");
}
console.log(fn());
4933701-fdd0b58bdee68ad0.png
image.png
  • async关键放在函数前,async关键字后意味着函数将返回一个Promise。

在函数前添加async关键字后意味着函数将返回一个Promise,JavaScript编译器会自动函数返回值转换为一个Promise。

async function fn(){
  return 1;
}
fn().then(alert);//1
function fn(){
    return Promise.resolve(1);
}
fn().then(alert);//1
fn().then(console.log);//1

如果要获取async函数的执行结果,需要调用Promise对象的then或catch来为其注册回调函数。

async function fn(){
    return 1;
}
fn().then(result=>console.log(result));//1

如果async函数执行完毕返回的Promise对象没有注册回调函数,比如函数内部做了一次for循环此时函数的调用就只是执行了函数体,这和普通的函数并没有区别。唯一的不同之处在于函数体执行完毕后返回的是一个Promise对象。

async function fn(){
    for(let i=0; i<10; i++){
        console.log("async fn:", i);
    }
}
console.log(fn());
ES7 async/await_第1张图片
image.png

async函数的执行会返回一个Promise对象,并将内部的值进行promise封装,如果Promise对象通过then或catch方法注册了回调函数,async函数执行完毕后,注册的回调函数会放入到异步队列中等待执行。如果只是async函数则和promise一样,但有了await之后就不一样的,await关键字只能放到async函数中,await等待的是什么呢?

await

await等待的是一个表达式,这个表达式的计算结果是Promise对象或其他值,换句话说await可以等待任意表达式的结果。如果await等到的不是一个Promise对象,那么await表达式的运算结果就是它等到的东西。如果await等到的是一个Promise对象,await就会阻塞后续代码,等到Promise对象resolve,然后得到resolve的值作为await表达式的运算结果。

这也就是await必须用在async函数中的原因,async函数调用不会造成阻塞,async函数内部所有的阻塞都被封装在一个Promise对象中异步执行。

let result = await promise;
  • await关键字的含义是让JavaScript编译器等待Promise并返回结果

await的意思是让JavaScript编译器等待Promise结束,然后再输出结果。这里并不会占用CPU资源,因为JavaScript引擎可以同时执行其它任务或脚本或处理事件。

async function fn(){
    
    let promise = new Promise((resolve, reject)=>{
        setTimeout(()=>resolve("done"), 1000);
    });
    let result = await promise;//wait till the promise resolve
    console.log(result);//done
}
fn();

fn函数执行时会在let result = await promise位置暂停,直到Promise返回结果,因此代码会在1秒后在控制台输出done。

  • await只能在async中运行

await不能单独使用,必须在async函数的作用域下使用,否则将会报异常Error:await is only valid in async function

function fn(){
    let promise = new Promise((resolve, reject)=>{
        setTimeout(()=>resolve("done"), 1000);
    });
    let result = await promise;//Uncaught SyntaxError: await is only valid in async function
    console.log(result);
}
fn();

例如:摇色子等待3秒后得到最终的结果

function fn(){
    let val = parseInt(Math.random() * 6 + 1);
    let promise = new Promise((resolve, reject)=>{
        setTimeout(()=>resolve(val), 3000);
    });
    return promise;
}
async function main(){
    let val = await fn();
    console.log(val);
}
main();

例如:摇色子猜大猜小,成功与失败的处理。

function fn(type){
    return new Promise((resolve, reject)=>{
        let val = parseInt(Math.random() * 6 + 1);
        if(val > 3){
            if(type === "big"){
                resolve(val);
            }else{
                reject(val);
            }
        }else{
            if(type === "big"){
                reject(val);
            }else{
                resolve(val);
            }
        }
        setTimeout(()=>resolve(val), 3000);
    });
}
async function main(){
    try{
        let val = await fn("big");
        console.log("win:", val);
    }catch(error){
        console.error("fail:", error);
    }
}
main();

例如:有两个色子都买大,猜成功则返回两个的值,猜失败则返回第一个失败的结果。

function fn(type){
    return new Promise((resolve, reject)=>{
        let val = parseInt(Math.random() * 6 + 1);
        if(val > 3){
            if(type === "big"){
                resolve(val);
            }else{
                reject(val);
            }
        }else{
            if(type === "big"){
                reject(val);
            }else{
                resolve(val);
            }
        }
        setTimeout(()=>resolve(val), 3000);
    });
}
Promise.all([fn("big"), fn("big")]).then(
    (val)=>console.log("resolve:", val), 
    (val)=>console.log("reject:",val)
);

例如:话费充值,当用户输入电话号码后先查找电话号码所在的省市,在根据省市找到可能的重置面额。

ES7 async/await_第2张图片
charge

创建项目安装依赖

$ mkdir charge && cd charge
$ npm init
$ npm i --save express
$ npm i --save body-parse
$ npm i -g supervisor

创建服务器

$ vim index.js
const express = require("express");
const bodyParser = require("body-parser");
const app = express();

app.use(express.static("public"));
app.use(bodyParser.json());

app.post("/location", (req, res, next)=>{
    const phone = req.body.phone;
    setTimeout(()=>{
        res.json({error:false, code:200, message:"success", result:{province:"湖南", city:"长沙"}});
    }, 1000);
});
app.post("/facelist", (req, res, next)=>{
    const province = req.body.province;
    const city = req.body.city;
    setTimeout(()=>{
        res.json({error:false, code:200, message:"success", result:["20元", "30元", "50元"]});
    }, 1000);
});

app.listen(3000, ()=>console.log("server start"));

创建视图界面

$ vim /public/index.html



    
    
    
    
    Document


    

手机话费充值



所属地区

访问页面 http://127.0.0.1:3000

你可能感兴趣的:(ES7 async/await)