《JavaScript应用程序设计》一一2.18 Promises与Deferreds

简介:

本节书摘来华章计算机出版社《JavaScript应用程序设计》一书中的第2章,第2.18节,作者:Eric Elliott 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.18 Promises与Deferreds

Promises作为一个对象,维护着成功与失败两个回调函数队列。与在异步/同步操作结束后执行的回调函数有所不同,你可以在异步操作的结尾处返回一个包含了一组回调函数的Promises。
Promises能够让你了解当前异步操作的进行状态,是在等待中,还是已完成,具体完成进度是多少。在整个过程中随时都可以向Promises中添加新的回调函数,当异步操作结束时,Promises会被正确解析,此时标识为成功的回调函数队列会被批量执行。
受CommonJS规范Promises/A的启发,jQuery实现了Promises并将这一规范推广至了JavaScript社区。jQuery使用Promises管理自己内部(包括Ajax请求在内)的异步任务队列,事实上,早在jQuery1.5中,所有Ajax方法执行后均会返回一个Promises,来看看它是如何工作的。

var whenDataFetched = $.getJSON(
  'https://graph.facebook.com/jsapplications'
);

asyncTest('Ajax promise API', function () {
  whenDataFetched
    .done(function (response) {
      ok(response,
        'The server returned data.');
      start();
    })
    .fail(function () {
      ok(true,
        'There was an error.');
      start();
    });
});

这个例子展示了,使用Ajax请求去获取“Programming JavaScript Applications”页面的元数据,因为所有jQuery中的Ajax辅助函数都会返回一个Promises,所以,你可以在whenDataFetched.done()中追加你的成功回调函数。
Promises与回调函数间的区别在于,Promises是调用者返回的一个对象,而不是传入调用者随后被执行的一个函数。Promises对象支持在异步操作过程中随时添加新的回调函数,并且会将回调函数彼此间的代码逻辑隔离开,所以使用Promises时回调函数并不一定要在异步操作开始前就传入。
deferred对象包含了一组方法,它被用来管理控制Promises。jQuery的Deferred()方法返回了一个与Promises功能极为类似的对象,这个对象上还拥有resolve()与reject()方法,这两个方法可以触发相应队列中的回调函数。假设你出于灵活性的考虑,想对现有的setTimeout()方法做改造,你想让它随时都可以接受回调函数的传入,而并不是仅能在首次定时调用时添加回调,你可以使用deferred对象来实现这个改造。

var timer = function timer(delay) {
  var whenTimedOut = $.Deferred(),
    promise = whenTimedOut.promise();

  promise.cancel = function (payload) {
    whenTimedOut.reject(payload);
  };

  setTimeout(function () {
    whenTimedOut.resolve();
  }, delay);

  return promise;
};

asyncTest('Deferred', function () {
  var startTime = new Date(),
    delay = 30,
    afterTimeout = 50,
    cancelTime = 100,
    myTimer = timer(delay),
    cancelTimer = timer(cancelTime);

  expect(4);

  myTimer.done(function () {
    ok(true,
      'First callback fired.');
  });

  myTimer.done(function () {
    var now = new Date();
    ok((now - startTime) > delay,
      'Delay works.'
      );
  });

  setTimeout(function () {
    ok(true,
      'Fires after timeout expires.');
  }, afterTimeout);

  setTimeout(function () {
    start();
  }, afterTimeout + 20);

  cancelTimer
    .done(function () {
      ok(false,
        'A canceled timer should NOT run .done().');
    })
    .fail(function () {
      ok(true,
        'A canceled timer calls .fail().');
    })
    .cancel();
});

Promises特别适用于那些有着一系列复杂调用序列的异步操作,因为往往在发起新的数据请求之前必须完成对多个数据源的请求。
回调函数会使得代码嵌套逻辑变得越来越深,但拥有了Promises,我们可以在任意数量的Promises对象被解析之后再决定下一步操作,下面是新timer()函数的应用:

var a = timer(60),
  b = timer(70),
  c = timer(40),
  tasks = [a, b, c];

asyncTest('Multiple dependencies.', function () {
  $.when(a, b, c).done(function () {
    ok(true, 'Runs when all promises resolve');
    start();
  });
});
相关文章
|
1月前
|
开发框架 前端开发 JavaScript
使用JavaScript、jQuery和Bootstrap构建待办事项应用
使用JavaScript、jQuery和Bootstrap构建待办事项应用
13 0
|
1月前
|
自然语言处理 JavaScript 前端开发
探索JavaScript中的闭包:理解其原理与实际应用
探索JavaScript中的闭包:理解其原理与实际应用
19 0
|
1月前
|
JavaScript 前端开发 算法
js开发:请解释什么是虚拟DOM(virtual DOM),以及它在React中的应用。
虚拟DOM是React等前端框架的关键技术,它以轻量级JavaScript对象树形式抽象表示实际DOM。当状态改变,React不直接操作DOM,而是先构建新虚拟DOM树。通过高效diff算法比较新旧树,找到最小变更集,仅更新必要部分,提高DOM操作效率,降低性能损耗。虚拟DOM的抽象特性还支持跨平台应用,如React Native。总之,虚拟DOM优化了状态变化时的DOM更新,提升性能和用户体验。
23 0
|
3天前
|
前端开发 JavaScript 编译器
深入解析JavaScript中的异步编程:Promises与async/await的使用与原理
【4月更文挑战第22天】本文深入解析JavaScript异步编程,重点讨论Promises和async/await。Promises用于管理异步操作,有pending、fulfilled和rejected三种状态。通过.then()和.catch()处理结果,但可能导致回调地狱。async/await是ES2017的语法糖,使异步编程更直观,类似同步代码,通过事件循环和微任务队列实现。两者各有优势,适用于不同场景,能有效提升代码可读性和维护性。
|
9天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
29天前
|
开发框架 JavaScript 前端开发
描述JavaScript事件循环机制,并举例说明在游戏循环更新中的应用。
JavaScript的事件循环机制是单线程处理异步操作的关键,由调用栈、事件队列和Web APIs构成。调用栈执行函数,遇到异步操作时交给Web APIs,完成后回调函数进入事件队列。当调用栈空时,事件循环取队列中的任务执行。在游戏开发中,事件循环驱动游戏循环更新,包括输入处理、逻辑更新和渲染。示例代码展示了如何模拟游戏循环,实际开发中常用框架提供更高级别的抽象。
13 1
|
1月前
|
JavaScript 前端开发
HTML JS 应用
HTML JS 应用
19 3
|
1月前
|
JavaScript 前端开发 算法
Vue.js的单向数据流:让你的应用更清晰、更可控
Vue.js的单向数据流:让你的应用更清晰、更可控
|
1月前
|
JavaScript 前端开发 API
Vue.js 深度解析:nextTick 原理与应用
Vue.js 深度解析:nextTick 原理与应用
|
1月前
|
Web App开发 JavaScript 前端开发
深入浅出:Node.js 在后端开发中的应用与实践
【2月更文挑战第13天】本文旨在探讨Node.js这一流行的后端技术如何在现代Web开发中被应用以及它背后的核心优势。通过深入分析Node.js的非阻塞I/O模型、事件驱动机制和单线程特性,我们将揭示其在处理高并发场景下的高效性能。同时,结合实际开发案例,本文将展示如何利用Node.js构建高性能、可扩展的后端服务,以及在实际项目中遇到的挑战和解决方案。此外,我们还将讨论Node.js生态系统中的重要工具和库,如Express.js、Koa.js等,它们如何帮助开发者快速搭建和部署应用。通过本文的探讨,读者将获得对Node.js在后端开发中应用的深入理解,以及如何有效利用这一技术来提升开发效率
100 2