Skip to content

Instantly share code, notes, and snippets.

@zhanhongtao
Created March 8, 2015 01:08
Show Gist options
  • Save zhanhongtao/3cf932dcdc238a320f9c to your computer and use it in GitHub Desktop.
Save zhanhongtao/3cf932dcdc238a320f9c to your computer and use it in GitHub Desktop.
Promise + Yield
// 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