Created
March 8, 2015 01:08
-
-
Save zhanhongtao/3cf932dcdc238a320f9c to your computer and use it in GitHub Desktop.
Promise + Yield
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Promise | |
// 1. p1 | |
function p1(value) { | |
return new Promise(function(resolve, reject) { | |
setTimeout(function() { | |
resolve(value); | |
}, 200); | |
}); | |
} | |
// 2. p2 | |
function p2(value) { | |
return new Promise(function(resolve, reject) { | |
setTimeout(function() { | |
resolve(value * 10); | |
}, 100); | |
}); | |
} | |
// 1. chain/then | |
p1(1).then(function(res) { | |
console.log('1:', res); | |
}); | |
// 2. pipe | |
p1(2).then(function(v) { | |
return v * 10; | |
}).then(function(res) { | |
console.log('2-pipe:', res); | |
}); | |
// 2.1 pipe(promise) | |
console.time('pipe'); | |
p1(2).then(function(v) { | |
return p2(v * 10); | |
}).then(function(res) { | |
console.timeEnd('pipe'); | |
console.log('2.1-return-promise:', res); | |
}); | |
// 2.2 == 2.1 | |
var promise = p1(2).then(function(v) { | |
return p2(v * 10); | |
}); | |
promise.then(function(v) { | |
console.log('2.2-return-promise: ', v); | |
}); | |
// 3. no pipe | |
var promise = p1(3); | |
promise.then(function(v) { | |
console.log('3-1: ', v); | |
return p2(3); | |
}); | |
promise.then(function(v) { | |
console.log('3-2: ', v); | |
}); | |
// 4. Promise.all Parallel | |
console.time('all'); | |
var promise = Promise.all([p1(4.1), p2(4.2)]); | |
promise.then(function(value) { | |
console.timeEnd('all'); | |
console.log('all:', value); | |
}); | |
// 5.1 Promise.resolve | |
// 5.2 Promise.reject 类似于 Promisel.resolve | |
var promise = Promise.resolve(5); | |
promise.then(function(res) { | |
console.log('Promise.resolve:', res); | |
}); | |
// 6. Promise.race | |
var promise = Promise.race([p1(6.1), p2(6.2)]); | |
promise.then(function(value) { | |
console.log(value); | |
}); | |
// 7.1 Promise.catch(onRejected); | |
// 7.2 promise.then(onFulFilled, onRejected); | |
function p3() { | |
return new Promise(function(resolve, reject) { | |
setTimeout(function() { | |
reject(0); | |
}, 100); | |
}); | |
} | |
p3().catch(function(code) { | |
console.log('catch: ', code); | |
}).then(null, function() { | |
console.log('No!'); | |
}); | |
// Generator | |
function* gen() { | |
yield 1; | |
yield 2; | |
yield 3; | |
} | |
// iterator | |
var g = gen(); | |
// 1. output | |
var res = g.next(); | |
while (res.done == false) { | |
console.log(res); | |
res = g.next(); | |
} | |
// rewrite | |
// input by arguments | |
function* gen(n) { | |
// input by next | |
var a = yield n; | |
var b = yield n + 1; | |
var c = yield n + 2; | |
console.log('n.a.b.c: ', n, a, b, c); | |
} | |
var n = 10; | |
var g = gen(n); | |
var res = g.next(n); | |
while(res.done == false) { | |
console.log(res); | |
res = g.next(res.value * 10); | |
} | |
// gen async | |
function* gen() { | |
var v1 = yield p1(1) + a; | |
var v2 = yield p2(2); | |
console.log('v: ', v1, v2); | |
} | |
var g = gen(); | |
var res = g.next(); | |
while(res.done == false) { | |
// res.value is promise. | |
console.log(res.value); | |
// input ? | |
res = g.next(); | |
} | |
// Boom! | |
var g = gen(); | |
var res = g.next(); | |
while(res.done == false) { | |
var promise = res.value; | |
promise.then(g.next); | |
// res ? | |
} | |
// Recursion | |
// generator + promise | |
function onFulFilled(res) { | |
try { | |
res = g.next(res); | |
} catch(e) { | |
throw e; | |
// console.log(e); | |
} | |
next(res); | |
} | |
function next(res) { | |
if (res.done) return; | |
// #promise! | |
// 需要返回 promise. | |
// 非 promise 时, 转换成 promise | |
// Promise.resolve/Promise.reject | |
// Promise.all/Promise.race | |
// new Promise(function(resolve, reject) {}) | |
var promise = res.value; | |
promise.then(onFulFilled); | |
} | |
var g = gen(); | |
onFulFilled(); | |
// 异常处理 | |
// 1. 重来 | |
// 2. 报错 - 异常 | |
// 3. 返回错误 | |
// End! | |
// #co | |
var slice = Array.prototype.slice; | |
function isPromise(obj) { | |
return !!obj && typeof obj.then == 'function'; | |
} | |
function thunkToPromise(thunk) { | |
var ctx = this; | |
return new Promise(function(resolve, reject) { | |
thunk.call(ctx, function(err, response) { | |
if (err) return reject(err); | |
else if (arguments.length > 2) { | |
response = slice.call(arguments, 1); | |
} | |
resolve(response); | |
}); | |
}); | |
} | |
function arrayToPromise(array) { | |
return Promise.all( | |
array.map(toPromise, this) | |
); | |
} | |
// @todo: Generator | |
function toPromise(obj) { | |
if (isPromise(obj)) { | |
return obj; | |
} | |
if( typeof obj == 'function') { | |
return thunkToPromise(obj); | |
} | |
if (Array.isArray(obj)) { | |
return arrayToPromise(obj); | |
} | |
return obj; | |
} | |
function co(gen){ | |
var ctx = this; | |
if (typeof gen == 'function') { | |
gen = gen.call(this); | |
} | |
return new Promise(function(resolve, reject) { | |
onFulFilled(); | |
function onFulFilled(response) { | |
var ret; | |
try { | |
ret = gen.next(response); | |
} catch(e) { | |
reject(e); | |
} | |
next(ret); | |
} | |
function onRejected(err) { | |
var ret; | |
try { | |
ret = gen.throw(err); | |
} catch(e) { | |
return reject(e); | |
} | |
next(ret); | |
} | |
function next(ret) { | |
if (ret.done) { | |
return resolve(ret.value); | |
} | |
var value = toPromise(ret.value); | |
if (value && isPromise(value)) { | |
return value.then(onFulFilled, onRejected); | |
} | |
return reject(); | |
} | |
}); | |
} | |
// test. | |
function t1() { | |
return new Promise(function(resolve, reject) { | |
setTimeout(function() { | |
resolve(1); | |
}, 100); | |
}); | |
} | |
function t2() { | |
return function(done) { | |
setTimeout(function() { | |
done(null, 2); | |
}, 500); | |
}; | |
} | |
// 串行 | |
function *tq() { | |
console.time('tq'); | |
var v1 = yield t1(); | |
var v2 = yield t2(); | |
console.timeEnd('tq'); | |
console.log( 'v: ', v1, v2 ); | |
} | |
// 并行 | |
function *ts() { | |
console.time('ts'); | |
var vs = yield [t1(), t2()]; | |
console.timeEnd('ts'); | |
console.log( 'v: ', vs ); | |
} | |
co(tq); | |
co(ts); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment