ES7两个亮点Async和Object.observe

Author image Cloud on 前端 , Web , ES7
Javacript 6规范将在2015年6月完成,现在谈ES7是否太早了呢?其实不是,因为ES7的一些特性已经开始进入浏览器,比如Chrome,ES7和ES6在时间进度上不会像ES5和ES6那样相差很大。  Javascript 7主要亮点是在事件机制和异步编程,这两点主要体现在:  1. Object.observe使得模型和视图之间很容易同步。  2. async函数更易于异步编程,能够实现拉Pull或推Push。  这两点提高基础是因为JS6中引入了使用 => 代表函数,箭头函数如下例:////ES5function(x, y) { return

  Javacript 6规范将在2015年6月完成,现在谈ES7是否太早了呢?其实不是,因为ES7的一些特性已经开始进入浏览器,比如Chrome,ES7和ES6在时间进度上不会像ES5和ES6那样相差很大。

  Javascript 7主要亮点是在事件机制和异步编程,这两点主要体现在:

  1. Object.observe使得模型和视图之间很容易同步。

  2. async函数更易于异步编程,能够实现拉Pull或推Push。

  这两点提高基础是因为JS6中引入了使用 => 代表函数,箭头函数如下例:

////ES5
function(x, y) { return x + 1; }
function(x, y) { return x + y; }
//ES6
X => X+1;
(x,y) => x+ y;
 


Object.observe

当前MVC模式在Angular.JS等冲击下已经变成了View视图和Model模型两个, 控制器由事件驱动机制替代,见 :MVI是一种Reactive MVC


那么为什么JS不能自然支持事件通知机制呢?ES7引入了Object.observe:

var person = {};
var changesHandler = changes => console.log(changes);
Object.observe(person, changesHandler);


这样,当person的内容有更改,将自动触发changes函数,如下:


person = {
  name: " jdon"
}
  如果person的名称从jdon改为jdon.com:
person = {
  name: " jdon.com"
}


这种name内容变化,将触发函数changes输出:


[
    {
        "type":"update",
        "name":"name",
        "oldValue: "jdon"
    }
]


如果person增加内容:

person = {
  name: " jdon.com"
  employer: "banq"
}


激活函数输出:


[
    {
        "type":"new",
        "name":"employer",
    }
]


如果person删除内容employer,那么输出是:

[
    {
        "type":"delete",
        "name":"employer",
        "oldValue: "banq"
    }
]


解除观察是:

Object.unobserve(person, changesHandler);


为了防止事件风暴,ES7使用了 Event Loop Queue + Microtasks,当事件处理器EventHandler发出改变事件给ChangeHandler以后,ChangeHandler不会排队在队列后面,而是替换当前EventHandler位置,这样在浏览器渲染页面之前完成所有事件通知:

js7.png


 

易于异步编程

如何使得异步编程如同同步堵塞编程那么简单方便?


function getStockPrice(name) {
    var symbol = getStockSymbol(name);
    var price = getStockPrice(symbol);
    return price;
}


这段代码中var price = getStockPrice(symbol);是一段拉取Pull,必须堵塞等到返回值。但是等待不一定要堵塞,可以如下:

getStockPrice("Devine Inc.", price => { … });


这段代码其实是推Push,价格price数据作为参数推入。但是当price进来时还需要判断,如果price值是错误error的情况如何处理:

function getStockPrice(name, cb) {
    getStockSymbol(name, (error, symbol) => {
        if (error) {
            cb(error);
        }
        else {
            getStockPrice(symbol, (error, price) => {
                if (error) {
                    cb(error);
                }
                else {
                    cb(price);
                }
            })
        }
    })
}


这段代码中有多个丑陋的if error判断,我们引入promise:


promise.then(value => {…}, error => {…});


我们看看下面同步代码和异步代码的比较:


function getStockPrice(name) {
    var symbol = getStockSymbol(name);
    var price = getStockPrice(symbol);
    return price;
}

上面是同步,下面是异步


function getStockPrice(name) {
    return getStockSymbol(name).
         then(symbol => getStockPrice(symbol));
}


可以看出来异步和同步代码两者完全不同,而在ES7中异步实现代码:


async function getStockPrice(name) {
    var symbol = await getStockSymbol(name);
    var price = await getStockPrice(symbol);
    return price;
}


ES7引入了async这个定义。它等同于在ES6中使用Task.js库包的如下写法:


function* getStockPrice(name) {
    var symbol = yield getStockSymbol(name);
    var price = yield getStockPrice(symbol);
    return price;
}
var result = spawn(getStockPrice.bind(null, "Pfizer"));
result.then(console.log, console.error);


ES7的类型如下:

js71.png