首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

标准库中的新对象和类型-3

标准库中的新对象和类型-3

这是为使用 promise 而重构的代码。上面的清单中包含的逻辑现在分解为不同的函数,每个函数使用一个                promise。结果得到的代码更长,但更整洁:
清单 7.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
let bookOrder = {'isbn': '978-0375504525', 'qty': 1};

function processBookOrders() {
  getNextOrder()
    .then((order) => doWeCarryThisBook(order))   
    .then((order) => isItInStock(order))
    .catch((err) => console.log(err.message));
}

processBookOrders();

function getNextOrder() {
  let promise = new Promise(
    function(resolve, reject) {
      console.log('Getting the next order');
      // pretend this is an async call to an orders database
      setTimeout(function() {
        let success = true;
        if (success)
          resolve(bookOrder);
        else
          reject(Error('No more orders!'));
      }, 1000);
    }
  );
  return promise;
}

function doWeCarryThisBook(order) {
  let promise = new Promise(
    function(resolve, reject) {
      console.log(`Looking for ISBN ${order.isbn}`);
      // pretend this is an async call to a books database
      setTimeout(function() {
        if (order.isbn == '978-0375504525') {
          console.log('The book title is \'As I Lay Dying.\'');
          resolve(order);
        } else {
          reject(Error('This is not a book we carry.'));
        }
      }, 1000);
    }
  );
  return promise;
}

function isItInStock(order) {
  let promise = new Promise(
    function(resolve, reject) {
      // pretend this is an async call to check stock levels
      setTimeout(function() {
        if (order.qty == 1) {
          console.log('The book is in stock!');
          resolve(order);
        } else {
          reject(Error('We do not have enough copies of the book in stock.'));
        }
      }, 1000);
    }
  );
  return promise;
}




清单顶部精简的 processBookOrders()                函数清楚表明了代码的用途。它获取下一个订单,检查书店内是否有这本书,然后检查该书的库存水平。如果这里调用的任何函数(getNextOrder()、doWeCarryThisBook()                或 isItInStock())通过其 reject 子句返回一个 JavaScript                Error 对象,该函数将停止运行。否则,该函数将进入下一个 then                语句。链接多个流程的能力非常强大。
可以尝试更改 bookOrder.isbn 或 bookOrder.qty 的值,或者将                getNextOrder() 中的代码改为                success = false。订单将失败,并返回合适的 Error 对象。
实际情况显然更为复杂。在我的经验中,开发人员将使用从库传回的                Promise,所以我预料大部分开发人员首先会使用它们,而不是构造它们。随着时间的推移,更多开发人员可能构建自己的                Promise 供其他模块使用。
关于                Promise,还有更多内容可以介绍,但这些内容足够另外写一篇文章了。幸运的是,对于在深入分析某个事物之前不想使用它的人,原始的回调和事件并未消失,所以您无需立即采用此特性。
动态代理使用动态代理进行 JavaScript 编程已经非常流行,但 ECMAScript 6 标准化了新的 Proxy                类型。拥有标准化的方法,可帮助我们避免库之间发生意外冲突和/或混淆。实质上,Proxy                实现了“拦截”行为,使一个对象能插到另一个对象前面。然后在任何针对原始目标的方法调用或属性引用上,首先使用拦截对象。
将对象的方法替换为另一种定义,这对于 ECMAScript 并不新奇,但 Proxy                类型这么做的频率更高。—它甚至能拦截目标对象上不存在的请求 —— 方法调用、属性引用等。
一个例子胜过千言万语,所以让我们来编写一些代码。传统上,会使用方法调用日志来演示代理的功能,所以我也会这么做。我们稍后还会介绍                Person 类,我们在这些文章中大量使用了它。
为增添乐趣,在构造后,我会在 Person 对象上放入一些有趣的方法。将这些方法添加到这里,也会表明动态代理可用于任何                ECMAScript 对象,无论它是如何构造或定义的:
清单 8.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var firstNameS = Symbol('firstName');
var lastNameS = Symbol('lastName');
var ageS = Symbol('age');
  
class Person {
  constructor(firstName, lastName, age) {
    this[firstNameS] = firstName;
    this[lastNameS] = lastName;
    this[ageS] = age;
  }
};

var ted = new Person('Ted', 'Neward', 45);

ted.sayHowdy = function() {
  console.log(this[firstNameS] + ' says howdy!');
};

ted.waveGoodbye = function(msg) {
  return '' + msg + ' Buh-bye!';
};

ted.sayHowdy();
console.log(ted.waveGoodbye('See you next time!'));




我们现在有两个方法:sayHowdy() 不接受参数,waveGoodbye()                接受一个参数并返回一个结果。它们本身不是很有趣,但它们将代表我们想捕获的方法。每次调用其中一个方法时,我们希望在控制台中能够看到一条消息显示“method                invoked”,理想情况下,还伴随一些有关该方法调用的有趣信息。
在我们忙碌时,能看到何时访问了属性该有多好!我们可以使用此特性检索值或设置它。可以通过代理这么做,也可以通过拦截构造函数调用和其他不常用的调用来实现此目的。实质上,代理可以拦截您对对象执行的任何操作,使您有机会执行其他操作,比如插入某个额外的行为。
返回列表