Last active
July 17, 2016 07:40
-
-
Save gaogao-9/182096d32df1e6e0f0e0581396578330 to your computer and use it in GitHub Desktop.
ObservableはESと干渉しそうなので、仮名としてGaobservableにしました。
This file contains hidden or 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
"use strict"; | |
const resolverSymbol = Symbol("resolver"); | |
const notifierListSymbol = Symbol("notifierList"); | |
const cancelSymbol = Symbol("cancel"); | |
class Gaobservable{ | |
constructor(resolver){ | |
if(typeof(resolver) !== "function") throw new TypeError(`Gaobservable resolver ${resolver} is not a function`); | |
this[resolverSymbol] = resolver; | |
this[notifierListSymbol] = []; | |
} | |
tap(notifier){ | |
if(typeof(notifier) !== "function") return this; | |
this[notifierListSymbol].push(notifier); | |
return this; | |
} | |
toPromise(){ | |
const resolver = this[resolverSymbol]; | |
const notifierList = this[notifierListSymbol]; | |
const promise = new Promise(function executor(promiseResolve, promiseReject){ | |
const data = []; | |
let finalizer; | |
try{ | |
finalizer = resolver(resolve, reject, add, notify); | |
} | |
catch(err){ | |
reject(err); | |
} | |
function resolve(){ | |
if(typeof(finalizer) === "function"){ | |
try{ | |
finalizer(); | |
} | |
catch(err){ | |
finalizer = null; | |
reject(err); | |
return; | |
} | |
} | |
promiseResolve(data); | |
} | |
function reject(reason){ | |
if(typeof(finalizer) === "function"){ | |
try{ | |
finalizer(); | |
} | |
catch(err){ | |
finalizer = null; | |
reject(err); | |
return; | |
} | |
} | |
promiseReject(reason); | |
} | |
function add(datum){ | |
notify(datum); | |
data.push(datum); | |
} | |
function notify(datum){ | |
try{ | |
for(var i=0,iLen=notifierList.length;i<iLen;i++){ | |
notifierList[i](resolve, reject, datum); | |
} | |
} | |
catch(err){ | |
reject(err); | |
} | |
} | |
}); | |
return promise; | |
} | |
toCancelable(){ | |
const promise = this.toPromise(); | |
let isCanceled = false; | |
let cancelReason, reject; | |
function cancel(reason){ | |
if(!isCanceled){ | |
isCanceled = true; | |
cancelReason = reason; | |
} | |
if(reject) reject({ | |
token: Gaobservable.cancelToken, | |
reason: cancelReason, | |
}); | |
} | |
const cancelPromise = new Promise((_, promiseReject)=> { | |
reject = promiseReject; | |
if(isCanceled) cancel(); | |
}); | |
return [Promise.race([promise, cancelPromise]), cancel]; | |
} | |
static create(resolver, notifier){ | |
return new Gaobservable(resolver) | |
.tap(notifier) | |
.toPromise(); | |
} | |
static get cancelToken(){ return cancelSymbol; } | |
} | |
export default Gaobservable |
This file contains hidden or 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
import Gaobservable from "./Gaobservable" | |
Promise.resolve("begin") | |
.then((data)=> new Gaobservable((resolve, reject, add, notify)=> { | |
console.log(data); // "begin" | |
let cnt = 10; | |
const timerId = setInterval(()=>{ | |
add(cnt--); | |
}, 100); | |
return ()=> { | |
clearInterval(timerId); | |
console.log("finalized"); | |
}; | |
}) | |
.tap((resolve, reject, data)=> { | |
console.log("tapped:", data); | |
if(!data) resolve(); | |
}) | |
.toPromise()) | |
.then((data)=> { | |
return data.reduce((a,b)=> a+b); | |
}) | |
.then((data)=> { | |
console.log(data); // 55 | |
}) | |
.then(()=> Gaobservable.create((resolve, reject, add, notify)=> { | |
throw new Error("ぬるぽ"); | |
})) | |
.catch((err)=> { | |
console.log("error:", err.message); // "error: ぬるぽ" | |
}); | |
/* 実行結果 | |
begin | |
tapped: 10 | |
tapped: 9 | |
tapped: 8 | |
tapped: 7 | |
tapped: 6 | |
tapped: 5 | |
tapped: 4 | |
tapped: 3 | |
tapped: 2 | |
tapped: 1 | |
tapped: 0 | |
finalized | |
55 | |
error: ぬるぽ | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment