dojo基础:dojo/request

本文详细介绍 dojo/request 的使用方法,包括如何向服务器请求文本文件、处理错误信息、提交数据等。同时,介绍了 dojo/request 的 API 特性,如异步编程支持、请求定制选项等,并通过多个示例展示了不同场景下的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dojo/request(从dojo1.8之后才有的)在客户端产生一个对服务器的请求。下面主要介绍:

  • 如何向服务器请求获取一个文本文件,如何处理期间发生的错误信息,如何向服务器提交信息

dojo/request可以在不用重新加载页面的情况下,向服务器发送数据、获取在服务器上执行检索后的结果数据。dojo/request使用dojo/promise、dojo/Deferred实现异步编程。

dojo/request简介

看下面的例子:
require(["dojo/request"], function(request){
    request("helloworld.txt").then(
        function(text){
            console.log("The file's content is: " + text);
        },
        function(error){
            console.log("An error occurred: " + error);
        }
    );
});

在浏览器上,上面的代码使用XMLHttpRequest执行了一个HTTP GET请求helloworld.txt,并且返回一个dojo/promise/Promise对象。如果请求成功,则执行then()中的第一个函数,并且以请求结果作为参数;如果请求失败,则执行then()中的第二个函数,并且以错误消息对象作为参数。

dojo/rquest api

每个请求都需要一个end-point,dojo/request的第一个参数是用于请求的URL,第二个参数(可选)是一个自定义的请求对象,在这个对象中可以配置有关这次请求的各种参数。通常情况下使用dojo/request非常简单,只需要传递一个字符串,option参数是可省略的。让我们来看看option对象中的常用配置参数:
  • method: 用于本请求的HTTP方法(默认是GET,dojo/request/script会忽略这个参数);
  • query: 形如key=value的字符串,或者形如{key: 'value'}的对象,包含所有的query参数;
  • data: 字符串或对象(会被dojo/io-query.objectToQuery串行化成字符串),表示需要发送的数据(GET和DELET请求会忽略这个参数);
  • handleAs: 表示如何处理服务器端响应的字符串,默认"text",其他可能的值包括'json', 'javascript',以及'xml';
  • headers: 形如{'Header-Name': 'value'}的对象,包含请求所需要的各种头部属性;
  • timeout: 表示等待多少毫秒算超时的整数,一旦超时将取消请求并"拒绝(reject)"所返回的promise。
看下例子:
require(["dojo/request"], function(request){
    request.post("post-content.php", {
        data: {
            color: "blue",
            answer: 42
        },
        headers: {
            "X-Something": "A value"
        }
    }).then(function(text){
        console.log("The server returned: ", text);
    });
});


API的一致性还包括返回值:所有dojo/request方法都返回一个“保证(promise)”对象,这个promise对象最终会提供响应数据。
如果在发起请求时指定了某个响应内容解析器(通过handleAs参数),那么这个promise对象就会提供这个内容解析器的解析结果,否则它将直接返回响应的body部分的文本。
dojo/request所返回的promise对象具有一个普通promise没有的附加属性:response。这个属性本身也是一个promise,它将提供一个对象来更详细地描述这次响应:
  • url: 发起请求的最终URL(加上了query字符串);
  • options: 请求相关的参数;
  • text: 响应中数据的字符串表示;
  • data:对响应进行处理后返回的数据(如果handles参数指定了有效的解析方式);
  • getHeader(headerName): 用于获取请求头部参数的函数;如果某个provider没有提供头部信息,这个函数将返回null。

Provider(提供者,这里指能够提供某种请求处理方式的模块 ——译注)

在幕后,dojo/request是通过provider来发起请求的。对于每一个平台dojo都选好了一个合适的默认provider:浏览器使用dojo/request/xhr,Node.js使用dojo/request/node。需要指出的是,比较新的浏览器(IE9+,FF3.5+,Chrome7+,Safari4+)将使用心得XMLHttpRequest2事件,而不是XMLHttpRequest的onreadystatechange,那只有在更老的浏览器中才会使用。另外,Node.js的provider直接使用了http和https模块,这意味着不用在服务器端部署任何接受XMLHttpRequest请求的中间层。

实例:request.get 和request.post

在页面上展示文本文件的内容

使用request.get请求一个文本文件。
require(["dojo/dom", "dojo/on", "dojo/request", "dojo/domReady!"],
    function(dom, on, request){
        // Results will be displayed in resultDiv
        var resultDiv = dom.byId("resultDiv");

        // Attach the onclick event handler to the textButton
        on(dom.byId("textButton"), "click", function(evt){
            // Request the text file
            request.get("../resources/text/psalm_of_life.txt").then(
                function(response){
                    // Display the text file content
                    resultDiv.innerHTML = "<pre>"+response+"</pre>";
                },
                function(error){
                    // Display the error returned
                    resultDiv.innerHTML = "<div class=\"error\">"+error+"<div>";
                }
            );
        });
    }
);

Login demo

下面的例子使用POST向服务器发送用户名和密码,并展示登陆结果。
require(["dojo/dom", "dojo/on", "dojo/request", "dojo/dom-form"],
    function(dom, on, request, domForm){

        var form = dom.byId('formNode');

        // Attach the onsubmit event handler of the form
        on(form, "submit", function(evt){

            // prevent the page from navigating after submit
            evt.stopPropagation();
            evt.preventDefault();

            // Post the data to the server
            request.post("../resources/php/login-demo.php", {
                // Send the username and password
                data: domForm.toObject("formNode"),
                // Wait 2 seconds for a response
                timeout: 2000

            }).then(function(response){
                dom.byId('svrMessage').innerHTML = response;
            });
        });
    }
);

Headers demo


使用promise.response.getHeader访问header。在使用promise.response.then时,response一个具有数据属性的对象,而不是数据。

require(["dojo/dom", "dojo/on", "dojo/request", "dojo/dom-form"],
    function(dom, on, request, domForm){
        // Results will be displayed in resultDiv

        var form = dom.byId('formNode');

        // Attach the onsubmit event handler of the form
        on(form, "submit", function(evt){

            // prevent the page from navigating after submit
            evt.stopPropagation();
            evt.preventDefault();

            // Post the data to the server
            var promise = request.post("../resources/php/login-demo.php", {
                // Send the username and password
                data: domForm.toObject("formNode"),
                // Wait 2 seconds for a response
                timeout: 2000
            });

            // Use promise.response.then, NOT promise.then
            promise.response.then(function(response){

                // get the message from the data property
                var message = response.data;

                // Access the 'Auth-Token' header
                var token = response.getHeader('Auth-Token');

                dom.byId('svrMessage').innerHTML = message;
                dom.byId('svrToken').innerHTML = token;
            });
        });
    }
);

JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON简单说就是javascript中的对象和数组。 JSON介绍
1、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。
 
2、数组:数组在js中是中括号“[]”括起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种。

JSON encoded object
{
    "title":"JSON Sample Data",
    "items":[{
        "name":"text",
        "value":"text data"
    },{
        "name":"integer",
        "value":100
    },{
        "name":"float",
        "value":5.65
    },{
        "name":"boolean",
        "value":false
    }]
}
把handleAs设为“json”时,dojo/request就把response当作JSON数据,并把它解析为Javascript对象。
require(["dojo/dom", "dojo/request", "dojo/json",
        "dojo/_base/array", "dojo/domReady!"],
    function(dom, request, JSON, arrayUtil){
        // Results will be displayed in resultDiv
        var resultDiv = dom.byId("resultDiv");

        // Request the JSON data from the server
        request.get("../resources/data/sample.json.php", {
            // Parse data from JSON to a JavaScript object
            handleAs: "json"
        }).then(function(data){
            // Display the data sent from the server
            var html = "<h2>JSON Data</h2>" +
                "<p>JSON encoded data:</p>" +
                "<p><code>" + JSON.stringify(data) + "</code></p>"+
                "<h3>Accessing the JSON data</h3>" +
                "<p><strong>title</strong> " + data.title + "</p>" +
                "<p><strong>items</strong> An array of items." +
                "Each item has a name and a value.  The type of " +
                "the value is shown in parentheses.</p><dl>";

            arrayUtil.forEach(data.items, function(item,i){
                html += "<dt>" + item.name +
                    "</dt><dd>" + item.value +
                    " (" + (typeof item.value) + ")</dd>";
            });
            html += "</dl>";

            resultDiv.innerHTML = html;
        },
        function(error){
            // Display the error returned
            resultDiv.innerHTML = error;
        });
    }
);
除了在response中将数据编码格式设置为json外,还可以将header的Content-Type属性设为application/json,或使用服务端配置文件中配置,或在服务器端使用代码写到header中。

JSONP (Javascript Object Notation with Padding)

AJAX中的请求仅限于当前域中,如果需要从其它域中请求数据,就要乃至JSONP。使用JSONP时,在当前页面中添加一个脚本标签,会请求标签的src文件,服务器将数据包装在回调函数中。当解译response时,调用回调函数,并将请求的数据作为回调函数的第一个参数。使用dojo/request/script生成JSONP请求。
JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。
看下面的例子:
require(["dojo/dom", "dojo/on", "dojo/request/script",
        "dojo/json", "dojo/domReady!"
], function(dom, on, script, JSON){
    // Results will be displayed in resultDiv
    var resultDiv = dom.byId("resultDiv");

    // Attach the onclick event handler to the makeRequest button
    on(dom.byId('makeRequest'),"click", function(evt){

        // When the makeRequest button is clicked, send the current
        // date and time to the server in a JSONP request
        var d = new Date(),
            dateNow = d.toString();
        script.get("../resources/php/jsonp-demo.php",{
            // Tell the server that the callback name to
            // use is in the "callback" query parameter
            jsonp: "callback",
            // Send the date and time
            query: {
                clienttime: dateNow
            }
        }).then(function(data){
            // Display the result
            resultDiv.innerHTML = JSON.stringify(data);
        });
    });
});
由于response是javascript代码,不是JSON,因此需要在将response的header的Content-Type设置application/javascript。
Using JSONP to request Dojo pull requests from the GitHub API
require(["dojo/dom", "dojo/on", "dojo/request/script",
        "dojo/dom-construct", "dojo/_base/array",
        "dojo/domReady!"
], function(dom, on, script, domConstruct, arrayUtil){
    var pullsNode = dom.byId("pullrequests");

    // Attach the onclick event handler to tweetButton
    on(dom.byId("pullrequestsButton"), "click", function(evt){
        // Request the open pull requests from Dojo's GitHub repo
        script.get("https://api.github.com/repos/dojo/dojo/pulls", {
            // Use the "callback" query parameter to tell
            // GitHub's services the name of the function
            // to wrap the data in
            jsonp: "callback"
        }).then(function(response){
            // Empty the tweets node
            domConstruct.empty(pullsNode);

            // Create a document fragment to keep from
            // doing live DOM manipulation
            var fragment = document.createDocumentFragment();

            // Loop through each pull request and create a list item
            // for it
            arrayUtil.forEach(response.data, function(pull){
                var li = domConstruct.create("li", {}, fragment);
                var link = domConstruct.create("a", {href: pull.url, innerHTML: pull.title}, li);
            });

            // Append the document fragment to the list
            domConstruct.place(fragment, pullsNode);
        });
    });
});

Reporting Status

dojo/request/notify提供了一种机制:使用dojo/request报告请求的状态。dojo/request/notify允许事件提供者发出事件,这个事件可以被监听,并且可以用于报告请求状态。为了监听一个事件,需要调用dojo/request/notify模块(有两个参数:事件名称和监听函数)的返回值。下面是事件提供者可以发出的事件:
  • start
  • end
  • load
  • error
  • done
  • stop
start和stop的监听不接收任何参数,send监听接收两个参数:代表请求的对象和取消函数。调用取消函数会在请求开始前取消请求。load、error和done的监听接收一个参数:代表来自服务器的response对象。
Using dojo/request/notify to monitor the progress of requests
require(["dojo/dom", "dojo/request", "dojo/request/notify",
        "dojo/on", "dojo/dom-construct", "dojo/query",
        "dojo/domReady!"],
    function(dom, request, notify, on, domConstruct){
        // Listen for events from request providers
        notify("start", function(){
            domConstruct.place("<p>Start</p>","divStatus");
        });
        notify("send", function(data, cancel){
            domConstruct.place("<p>Sent request</p>","divStatus");
        });
        notify("load", function(data){
            domConstruct.place("<p>Load (response received)</p>","divStatus");
        });
        notify("error", function(error){
            domConstruct.place("<p class=\"error\">Error</p>","divStatus");
        });
        notify("done", function(data){
            domConstruct.place("<p>Done (response processed)</p>","divStatus");
            if(data instanceof Error){
                domConstruct.place("<p class=\"error\">Error</p>","divStatus");
            }else{
                domConstruct.place("<p class=\"success\">Success</p>","divStatus");
            }
        });
        notify("stop", function(){
            domConstruct.place("<p>Stop</p>","divStatus");
            domConstruct.place("<p class=\"ready\">Ready</p>", "divStatus");
        });

        // Use event delegation to only listen for clicks that
        // come from nodes with a class of "action"
        on(dom.byId("buttonContainer"), ".action:click", function(evt){
            domConstruct.empty("divStatus");
            request.get("../resources/php/notify-demo.php", {
                query: {
                    success: this.id === "successBtn"
                },
                handleAs: "json"
            });
        });
    }
);

dojo/request/registry

dojo/request/registry提供了一种机制:根据不同的请求URL,提供不同的处理方式(provider)。
dojo/request/registry的语法:
request.register(url, provider, first);
dojo/request/registry的参数:
  • url:可以是string 、regEx或函数
string:如果请求的URL与这个url匹配就会使用这个provider;
regExp:如果url是一个正则表达式,请求的URL与其匹配就会使用这个provider;
函数:这个函数和函数的请求参数(url和option对象)会被传递,如果返回true,就会使用这个provider;
  • provider:用于处理请求;
  • first:一个可选的布尔参数。如果为true,在其它provider注册前注册这个provider。
Using dojo/request/registry to assign the provider based on the URL of requests
require(["dojo/request/registry", "dojo/request/script", "dojo/dom",
        "dojo/dom-construct", "dojo/on", "dojo/domReady!"],
    function(request, script, dom, domConstuct, on){
        // Registers anything that starts with "http://"
        // to be sent to the script provider,
        // requests for a local search will use xhr
        request.register(/^https?:\/\//i, script);

        // When the search button is clicked
        on(dom.byId("searchButton"), "click", function(){
            // First send a request to twitter for all tweets
            // tagged with the search string
            request("http://search.twitter.com/search.json", {
                query: {
                    q:"#" + dom.byId("searchText").value,
                    result_type:"mixed",
                    lang:"en"
                },
                jsonp: "callback"
            }).then(function(data){
                // If the tweets node exists, destroy it
                if (dom.byId("tweets")){
                    domConstuct.destroy("tweets");
                }
                // If at least one result was returned
                if (data.results.length > 0) {
                    // Create a new tweet list
                    domConstuct.create("ul", {id: "tweets"},"twitterDiv");
                    // Add each tweet as an li
                    while (data.results.length>0){
                        domConstuct.create("li", {innerHTML: data.results.shift().text},"tweets");
                    }
                }else{
                    // No results returned
                    domConstuct.create("p", {id:"tweets",innerHTML:"None"},"twitterDiv");
                }
            });
            // Next send a request to the local search
            request("../resources/php/search.php", {
                query: {
                    q: dom.byId("searchText").value
                },
                handleAs: "json"
            }).then(
                function(data){
                    dom.byId('localResourceDiv').innerHTML =
                        "<p><strong>" + data.name + "</strong><br />" +
                        "<a href=\"" + data.url + "\">" + data.url + "</a><br />";
                },
                function(error){
                    // If no results are found, the local search returns a 404
                    dom.byId('localResourceDiv').innerHTML = "<p>None</p>";
                }
            );
        });
    }
);


dojo/request/registry同样遵循dojo/request API(因此它本身就可以作为一个provider),不过增加了一个register函数:
<span style="font-size:14px;">// 如果一个请求的URL是"some/url",provider就会被用来处理这个请求
registry.register("some/url", provider);
 
// 如果一个请求的URL以"some/url"开始,provider就会被用来处理这个请求
registry.register(/^some\/url/, provider);
 
// 如果一个请求是一HTTP GET方法发送的,provider就会被用来处理这个请求
registry.register(
    function(url, options){
        return options.method === "GET";
    },
    provider
);
 
// 如果不能匹配到任何已注册的条件,默认provider将被使用
</span>
如果所有条件都不满足,而且也没有备用provider可用,那么当前环境的默认provider将被启用。由于dojo/request/registry符合dojo/request API,它可以作为默认provider:
<span style="font-size:14px;"><script>
    var dojoConfig = {
        requestProvider: "dojo/request/registry"
    };
</script>
<script src="path/to/dojo/dojo.js"></script>
<script>
    require(["dojo/request", "dojo/request/script"],
        function(request, script){
            request.register(/^\/jsonp\//, script);
            ...
        }
    );
</script></span>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值