ES6 Generator与JS异步编程

今天节目的主要内容有

  • 异步编程不得不说的一些事
  • Callback
  • Promise
  • Generator
  • Q&A

正式开始之前

免责声明

Want to learn ES6?

too much content

异步编程不得不说的一些事

var data = ajax( "http://some.url.1" );

console.log( data );
ajax( "http://some.url.1", function myCallbackFunction(data){
    console.log( data );
} );

A Program in Chunks

$('#wx-qrcode').bind('mouseenter', function () {
	var $this = $(this);
	if ($this.data('loaded')) {
		return;
	}	
	$this.data('loaded', true);
	$.ajax({
		url: '//wq.jd.com/wdcolumn/tempqrcode/tempqrcode',
		data: {
			orderid: pageInfo.orderId
		},
		dataType: 'jsonp',
		cache: true,
		success: function (result) {
			$this.siblings('.service-cont').find('img').attr({src: result.url});
		}
	});
});

A Program in Chunks

A Program in Chunks

$('#wx-qrcode').bind('mouseenter', function () {
	...
});
var $this = $(this);
if ($this.data('loaded')) {
	return;
}	
$this.data('loaded', true);
$.ajax({
	url: '//wq.jd.com/wdcolumn/tempqrcode/tempqrcode',
	data: {
		orderid: pageInfo.orderId
	},
	dataType: 'jsonp',
	cache: true,
	success: function (result) {
	}
});
$this.siblings('.service-cont').find('img').attr({src: result.url});

A Program in Chunks

  • setTimeout
  • ajax
  • UI event
  • File API
  • ......

Eventloop

Run-to-Completion

setTimeout

console.log('First Message');

setTimeout(function () {
    console.log('Second Message after 200ms');
}, 200);

Concurrency

Single Thread

Eventloop

ajax, File API, etc

asynchronous

Common Pattern 1

var res = {};

function foo(results) {
    res.foo = results;
}

function bar(results) {
    res.bar = results;
}

ajax( "http://some.url.1", foo );
ajax( "http://some.url.2", bar );

Common Pattern 2

var a, b;

function foo(x) {
    a = x * 2;
    if (a && b) {
        baz();
    }
}

function bar(y) {
    b = y * 2;
    if (a && b) {
        baz();
    }
}

function baz() {
    console.log( a + b );
}

ajax( "http://some.url.1", foo );
ajax( "http://some.url.2", bar );

Common Pattern 3

var a;

function foo(x) {
    if (a == undefined) {
        a = x * 2;
        baz();
    }
}

function bar(x) {
    if (a == undefined) {
        a = x / 2;
        baz();
    }
}

function baz() {
    console.log( a );
}

ajax( "http://some.url.1", foo );
ajax( "http://some.url.2", bar );

Callback

Nested Callbacks

listen( "click", function handler(evt){
    setTimeout( function request(){
        ajax( "http://some.url.1", function response(text){
            if (text == "hello") {
                handler();
            }
            else if (text == "world") {
                request();
            }
        } );
    }, 500) ;
} );

Callback Hell

What's the real problem of callbacks?

Scenario 1

doA( function(){
    doB();

    doC( function(){
        doD();
    } )

    doE();
} );

doF();
  • doA()
  • doF()
  • doB()
  • doC()
  • doE()
  • doD()

Scenario 2

doA( function(){
    doB();

    doC( function(){
        doD();
    } )

    doE();
} );

doF();

What if doA(..) or/and doC(..) aren't actually async ?

A -> B -> C -> D -> E -> F

Scenario 3

listen( "click", handler );

function handler() {
    setTimeout( request, 500 );
}

function request(){
    ajax( "http://some.url.1", response );
}

function response(text){
    if (text == "hello") {
        handler();
    }
    else if (text == "world") {
        request();
    }
}
  • not very reusable 
  • bad error handlling
  • no forks

Scenario 4

analytics.trackPurchase( purchaseData, function(){
    chargeCreditCard();
    displayThankyouPage();
} );

can you trust third-party?

function success(data) {
    console.log( data );
}

function failure(err) {
    console.error( err );
}

ajax( "http://some.url.1", success, failure );
function response(err,data) {
    // error?
    if (err) {
        console.error( err );
    }
    // otherwise, assume success
    else {
        console.log( data );
    }
}

ajax( "http://some.url.1", response );

Trying to Save Callbacks

Promise

Problems To Solve

  • IoC (inversion of control)
  • Sequentiality

Commen Pattern of Asynchronous

  1. Either success, or fail
  2. Resolved to 1 value
  3. The value never change

"Asynchronous Object"

.then()

Example

var cartPromise = getShoppingCart();

cartPromise.then(function (data) {
    showCartContents(data)
}, function () {
    console.log('no value')
})

Branches

var cartPromise = getShoppingCart();

cartPromise.then(function (data) {
    showCartContents(data)
}, function () {
    console.log('no data');
});


cartPromise.then(function (data) {
    showTotalPrice(data);
}, function () {
    console.log('no data');
])

cartPromise

.then

.then

Chainable

getShoppingCart().then(filterManJianSKU).then(getManJianSummary);

function filterManJianSKU(data){
    var result = [];
    $.each(data, function (i, product){
        if (product.isManJian){
            result.push(product.sku);
        }
    }

    return result;
}

function getManJianSummary (skus){
    return $.ajax({
        url: '/getManJianSummary.action',
        data: {
            skus: skus.join(',')
        },
        dataType: 'json'
    })
}

Every .then() call returns a new Promise object

Error Handling

doWork()
    .then(doWork)
    .then(doError)
    .then(doWork)
    .then(doWork, errorHandler)
    .then(doWork)

Variations 

  • Promise.all()
  • Promise.race()
  • Promise.first()

Can I use Promise now?

Yes!

jQuery since 1.5

Spec

Generator

function* allOddNumber () {
	var current = 1;

	while (true) {
		yield current;
		current += 2;
	}
}

Basic Usage

.next() with parameter

function* allOddNumber () {
	var current = 1;
	var msg;

	while (true) {
		msg = yield current;
		console.log('Received message in generator: ' + msg);
		current += 2;
	}
}

var i = allOddNumber();
var curr = i.next();

while (true) {
	curr = i.next(curr.value * 2);

	if (curr.done || curr.value > 10) {
		break;
	}
}

Exception Handling

function *main() {
    var x = yield "Hello World";

    yield x.toLowerCase();  // cause an exception!
}

var it = main();

it.next().value;            // Hello World

try {
    it.next( 42 );
}
catch (err) {
    console.error( err );   // TypeError
}

Exception Handling

function* allOddNumber () {
	var current = 1;
	var msg;

	while (true) {
		msg = yield current;
		current += 2;
	}
}

var i = allOddNumber();
var curr = i.next();

while (true) {
	try {
		if (curr.value < 10)  {
			curr = i.next();
		}
		else {
			throw 'We only need Odd number less than 10';
		}
	}




}
	catch (e) {
		i.throw(e);
	}

Have nothing to do with async yet!

function* updateManJianSummary () {


	var cartInfo = yield getShoppingCart();
	var manjianSku = yield filterManJianSKU(cartInfo);
	var manjianInfo = yield getManJianSummary(manjianSku);
	showInfo(manjianInfo);





}
	try {
	}
	catch (e) {
		showErrorMessage();
	}

Generator with Promise

Can I use Generator today?

Edge 13+ / Firefox 27+ / Chrome 39+

But wait...

Also with JDF since 1.8.2 !!!!

checkout detail

Questions?

Links

ES6 Generator与JS异步编程

By loveky

ES6 Generator与JS异步编程

  • 1,605