zoukankan      html  css  js  c++  java
  • JavaScript异步编程2——结合XMLHttpRequest使用Promise

    1. 概述

    在上一篇文章《JavaScript异步编程1——Promise的初步使用》,简单介绍了一下Promise的初步使用。复习一下,Promise异步编程可以用如下的范式来编写:

    1. 定义一个函数(function A),这个函数返回一个Promise对象。
    2. Promise对象的参数也是一个function B,内部进行了一个异步操作(通常是JavaScript提供的API)。
    3. function B对象的参数是两个回调函数resolve和reject。如果函数内部进行的异步操作成功,回调resolve;否则回调reject。
    4. 调用function A,返回一个Promise对象,这样异步操作就启动了。
    5. 调用Promise对象的then方法,参数是resolve和reject的真正响应函数。当异步操作完成了,就会执行相应分支的响应函数。

    采用以上范式,可以通过Promise来进行Ajax操作,也就是XMLHttpRequest,毕竟这个操作在Web应用中实在太常见了。

    2. 详论

    首先仍然是准备一个HTML页面:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <script src="./3rdParty/jquery-3.5.1.js"></script>
        <title>样例</title>
    </head>
    
    <body>
        <div id = "container"> </div>
        <script src="./PromiseTest.js"></script>
    </body>
    
    </html>
    

    如果不使用Promise,那么相应的JavaScript代码为:

    $(function () {
    
        var url = "./1.json";
    
        var req = new XMLHttpRequest();
        req.open('GET', url);
    
        req.onload = function () {        
            if (req.status == 200) {
                console.log(req.response);
            } else {           
                throw new Error(req.statusText);
            }
        };
    
        req.onerror = function () {
            throw new Error("Network Error");
        };
    
        req.send();
    });
    

    可以看到这里仍然是通过事件机制来实现异步行为。接下来采用前面提到的编程范式将其改造成Promise机制:

    function get(url) {       
        return new Promise(function (resolve, reject) {      
            var req = new XMLHttpRequest();
            req.open('GET', url);
    
            req.onload = function () {
                //即使是404也会进入这个相应函数,所以需要检测状态
                if (req.status == 200) {
                    //完成许诺,返回响应文本
                    resolve(req.response);
                } else {
                    //完成未完成,返回错误
                    reject(Error(req.statusText));
                }
            };
    
            // 发生错误时的相应函数
            req.onerror = function () {
                reject(Error("Network Error"));
            };
    
            // 发送请求
            req.send();
        });
    }
    
    var addressUri = "./1.json";
    get(addressUri).then(function (response) {
        console.log("Success!", response);      
    }, function (error) {
        console.error("Failed!", error);
    }); 
    

    改造成Promise的过程与上一章并没有什么不同,只不过函数内部调用XMLHttpRequest的流程更加复杂些。这两个例子都是将事件改造成Promise,那不是意味着对于异步编程而言,Promise要优于事件呢?

    不能完全这么肯定,但是可以确定的是事件并不总是异步编程的最优实践。一个很显然的问题就是:事件很适合处理在同一对象上多次发生的事情,但是事件侦听器的响应函数可能并不是我们想要的——更多情况下,我们只想要直到两个状态,当异步操作完成的时候该做什么,当异步操作失败的时候又该做什么,而这正是Promise擅长处理的。

    例如这里的XMLHttpRequest操作,事件响应函数onload中的所有行为,并不都是异步请求成功时需要完成的,只有检测访问请求状态为200时候,才需要进行请求成功时的回调函数。使用Promise,可以更准确的进行异步行为。

    3. 参考

    1. Ajax原理-原生js的XMLHttpRequest对象意义
    2. Javascript异步编程的4种方法
  • 相关阅读:
    uva12436 回头再做一次
    Redhat中网络启动错误解决办法( Failed to start LSB: Bring up/down networking RTNETLINK answers: File exists)
    LNMP环境搭建Wordpress博客
    LNMP环境搭建Wordpress博客
    LAMP环境搭建一个Discuz论坛
    LAMP环境搭建一个Discuz论坛
    常见的SQL语句
    常见的SQL语句
    Linux系统中安装软件的几种方式
    Linux系统中安装软件的几种方式
  • 原文地址:https://www.cnblogs.com/charlee44/p/14670458.html
Copyright © 2011-2022 走看看