Dojo1.11官方教程文档翻译(4.7)Deferred入门

来源:互联网 发布:网络创世纪uo 音乐 编辑:程序博客网 时间:2024/06/06 11:37

原文地址:https://dojotoolkit.org/documentation/tutorials/1.10/declare/index.html
本翻译项目放在GitBook上,欢迎参与。
GitBook地址:https://www.gitbook.com/book/limeng1900/dojo1-11-tutorials-translation-in-chinese/details
转载请注明出处:http://blog.csdn.net/taijiedi13/ – 碎梦道


这篇教程中,你将了解使用Dojo’s Deferred实现的基础知识,它是轻松地进行异步活动的一种方式,例如Ajax调用。

入门

当你第一次听说“Deferred”时,它可能听起来像一个神秘对象,实际上它是异步操作(如Ajax)的有力工具。最简单的形式如一个Deferred等待直到一段时间后执行一个动作;本质上,你推迟该动作直到一个前置动作完成。Ajax就属于这种情况:在服务器成功返回信息之前, 我们不想执行一些动作。关键在于能够等待值的返回。在这篇教程中,我们将结合之前 Ajax tutorial 的知识并探索如何使用Deferred来提高异步行为的交互能力。

dojo/Deferred

Dojo对deferred对象的实现是dojo/Deferred(从0.3版本就开始出现),它在Dojo1.8版本进行了重构。现在起在实例化一个Deferred、动作或者将引用的回调之后,可以通过传递一个函数给then方法进行注册,在Deferred完成之后(a success)调用then方法。then方法也接收第二个参数:在Deferred被拒(an error)之后调用一个函数,该函数通常被称为errback。我们来看一个示例来帮助消化:

require(["dojo/Deferred", "dojo/request", "dojo/_base/array", "dojo/dom-construct", "dojo/dom", "dojo/domReady!"],    function(Deferred, request, arrayUtil, domConstruct, dom) {        // Create a deferred and get the user list        var deferred = new Deferred(),            userlist = dom.byId("userlist");        // Set up the callback and errback for the deferred        deferred.then(function(res){            arrayUtil.forEach(res, function(user){                domConstruct.create("li", {                    id: user.id,                    innerHTML: user.username + ": " + user.name                }, userlist);            });        },function(err){            domConstruct.create("li", {                innerHTML: "Error: " + err            }, userlist);        });        // Send an HTTP request        request.get("users.json", {            handleAs: "json"}).then(            function(response){                // Resolve when content is received                deferred.resolve(response);            },            function(error){                // Reject on error                deferred.reject(error);            }        );});

View Demo

在示例中,我们的创建一个Deferred并且注册一个回调和一个errback。我们也调用request.get——一个异步操作,来获取“users.json”。如果取回成功,它解决这个deferred并调用回调函数;如果取回失败,它将拒绝deferred并调用errback。

你可能会问自己,“我真的每次都要这么用dojo/Deferred么?”答案是“No”。Dojo所有的Ajax方法都返回dojo/promise/Promise,成功时回调,被拒时error:

require(["dojo/request", "dojo/_base/array", "dojo/dom-construct", "dojo/dom", "dojo/domReady!"],    function(request, arrayUtil, domConstruct, dom) {        var deferred = request.get("users.json", {            handleAs: "json"        });        deferred.then(function(res){            var userlist = dom.byId("userlist");            arrayUtil.forEach(res, function(user){                domConstruct.create("li", {                    id: user.id,                    innerHTML: user.username + ": " + user.name                }, userlist);            });        },function(err){            // This shouldn't occur, but it's defined just in case            alert("An error occurred: " + err);        });});

View Demo

我们用then来注册一个回调,如果Ajax调用成功,Deferred被解决,通常传递给load函数的第一个参数会传递给回调函数。如果Ajax调用失败,Deferred被拒,error会传递给errback。

在回调函数中,我们遍历服务器返回的users并且为每一个创建一个列表项,就像我们设置load属性。然而,使用一个Deferred,我们可以从动作中分离获取数据的取回动作(Ajax调用)。对动作的分离正是Deferred强大的一面。

链式

虽然一旦你熟悉Deferred就会发现它是一个相当简单的概念,但dojo/Deferred还包含着一些强力的特性。其中之一就是链式:then调用动作的结果就像一个新的Deferred,而不是回调返回的值。初看会很容易困惑,所以先看个例子。

比方说服务器不在返回users对象,而是返回每一个user值组成的list。这并不是很实用,所以我们注册一个回调来将这个list转换成更有用的东西。针对第一个then的结果注册的每个连续回调都有可用的users list传递给它。

require(["dojo/request", "dojo/_base/array", "dojo/json", "dojo/dom-construct", "dojo/dom", "dojo/domReady!"],    function(request, arrayUtil, JSON, domConstruct, dom) {        var original = request.get("users-mangled.json", {            handleAs: "json"        });        var result = original.then(function(res){            var userlist = dom.byId("userlist1");            return arrayUtil.map(res, function(user){                domConstruct.create("li", {                    innerHTML: JSON.stringify(user)                }, userlist);                return {                    id: user[0],                    username: user[1],                    name: user[2]                };            });        });        // Our result object has a `then` method that accepts a callback,        // like our original object -- but the value handed to the callback        // we're registering here is *NOT* the data from the Ajax call,        // but the return value from the callback above!        result.then(function(objs){            var userlist = dom.byId("userlist2");            arrayUtil.forEach(objs, function(user){                domConstruct.create("li", {                    innerHTML: JSON.stringify(user)                }, userlist);            });        });});

then方法的返回值指定为一个promise,它实现一个特定API。你可以前往the promises tutorial 了解更多信息,不过现在,只要知道一个promise提供一个then方法,该方法和Deferred的then完全一致。

重点要注意:原始Deferred不受链式影响,并且如果原始Deferred注册了一个回调,服务器的list仍然完好。

original.then(function(res){    var userlist = dom.byId("userlist3");    arrayUtil.forEach(res, function(user){        domConstruct.create("li", {            innerHTML: JSON.stringify(user)        }, userlist);    });});

View Demo

这个例子很随意,但是链式可以用来为你应用的消耗修改数据。例子里还可以这么做:

require(["dojo/request", "dojo/_base/array", "dojo/dom-construct", "dojo/dom", "dojo/domReady!"],    function(request, arrayUtil, domConstruct, dom) {        function getUserList(){            return request.get("users-mangled.json", {                handleAs: "json"            }).then(function(response){                return arrayUtil.map(response, function(user){                    return {                        id: user[0],                        username: user[1],                        name: user[2]                    };                });            });        }        getUserList().then(function(users){            var userlist = dom.byId("userlist");            arrayUtil.forEach(users, function(user){                domConstruct.create("li", {                    id: user.id,                    innerHTML: user.username + ": " + user.name                }, userlist);            });        });});

View Demo

现在任何使用getUserList的代码都将得到一个user对象列表。

Deferred 列表

有时你需要并行从多个源取回数据,还想在请求完成时收到通知。你可以设置某种叫做Deferred系统的Deferred,一项项返回,不过就像本教程第一个例子,你不用手动来做。Dojo1.8之前,用Dojo/DeferredList处理。1.8之后用dojo/promise/alldojo/promise/first来处理,这将在 promises tutorial教程中涉及。

小结

由于大部分JavaScript应用使用Ajax,就需要一个简单而优雅的注册操作,这正是dojo/Deferred所提供的。链式则让它变得更加简单。

资源

  • dojo/Deferred Reference Guide
  • dojo/Deferred API
  • Ajax with dojo/request Tutorial
  • Dojo Deferreds and Promises Tutorial
  • Future and Promises Wikipedia article
0 0
原创粉丝点击