搭配 async、await


ES8(ECMAScript 2017)新增了asyncawait语法,如〈Promise〉中谈过的,可以用来令非同步的流程,不用是透过回调函数,而像是顺序编写的语法。

Fetch API 有许多方法,都是返回Promise,因此搭配asyncawait语法,可以令程序更为简洁,例如〈简介 Fetch API〉中的第一个范例,可以改写为:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
</head>
<body>

    <button id='req'>获取表格</button>
    <div id="table"></div>

<script type="text/javascript">

    document.getElementById('req').onclick = async function() {
        let resp = await fetch('XMLHttpRequest-1.txt');
        let text = await resp.text();
        document.getElementById('table').innerHTML = text;
    };

</script>   

</body>
</html>

按我观看执行结果

await可以承接返回Promise的 API,直到有结果之后,流程才会往下一步,await只能编写在async标示的函数之中,然而,事件处理器可以标示为async,这使得程序编写起来简单许多。

来将〈简介 Fetch API〉中第二个范例改写为asyncawait

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
</head>
<body>

    新增书签:<br>
    网址:<input id="url" type="text">
    <span id="message" style="color:red"></span><br>
    名称:<input type="text">

<script type="text/javascript">    
    function params(paraObj) {
        return Object.keys(paraObj)
                     .map(name => {
                         let paraName = encodeURIComponent(name);
                         let paraValue = encodeURIComponent(paraObj[name]);                         
                         return `${paraName}=${paraValue}`.replace(/%20/g, '+');
                     })
                     .join('&');
    }

    document.getElementById('url').onblur = async function() {
        let reqString = params({ 
            url : document.getElementById('url').value 
        });

        let resp = await fetch('POST-1.php', {
            method : 'POST',
            headers : {
                'Content-Type' : 'application/x-www-form-urlencoded'
            },
            body : reqString
        });

        let text = await resp.text();
        if(text === 'existed') {
            document.getElementById('message').innerHTML = 'URL 已存在';
        }    

    };

</script>

</body>
</html>

按我观看执行结果

底下则是将〈简介 Fetch API〉中最后一个范例改写为asyncawait

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
</head>
<body>

    <body>
        ID:<input id="id">
        <button id="test">JSONP 测试</button>
        <span id="result"></span>
    </body>

<script type="text/javascript">

    document.getElementById('test').onclick = async function() {
        let id = document.getElementById('id').value;
        let result = document.getElementById('result');

        let resp = await fetch(`https://openhome.cc/Gossip/ECMAScript/samples/CORS-1.php?id=${id}`, {
            mode : 'cors'
        });
        let person = await resp.json();
        result.innerHTML = `${person.name}, ${person.age}`;
    };

</script>    

</body>
</html>

按我观看执行结果

当然,Promise是一种流畅风格,而asyncawait是另一种风格,就看各自偏好哪个了。


展开阅读全文