ãã¹ãŠã®è¯ãäžæ¥ã 仿¥ã¯ãJSãšã³ãžã³ã®promiseã¡ã«ããºã ã®å®è£
ãã©ã®ããã«æžãããã«ã€ããŠã話ããããšæããŸãã ãåç¥ã®ããã«ãæ°ããECMA Script 6æšæºã¯ããã»ã©åã«ãªãªãŒã¹ãããŠããããpromiseã®æŠå¿µã¯éåžžã«è峿·±ãããŸãWebéçºè
ã«ãã£ãŠäœ¿çšãããå€ãã®å Žæã«èŠããŸãã ãããã£ãŠãçŸä»£ã®JSãšã³ãžã³ã§ã¯ãããã¯ç¢ºãã«å¿
èŠãªãã®ã§ãã
泚æïŒãã®èšäºã«ã¯å€ãã®ã³ãŒãããããŸãã ãããžã§ã¯ãå
šäœã1人ã§äœæããããŸã ããŒã¿çã§ãããããã³ãŒãã¯çŸããé«å質ã§ããããã«èŠããããŠããŸããã ãã®ç©èªã®ç®çã¯ããã¹ãŠãå
éšã§ã©ã®ããã«æ©èœãããã瀺ãããšã§ãã ããã«ãå°ãé©åãããåŸããã®ã³ãŒãã䜿çšããŠãJavaScriptã«é¢ä¿ãªããçŽç²ã«Javaã§ãããžã§ã¯ããäœæã§ããŸãã
ã³ãŒããæžãå§ããæåã®ããšã¯ããã¹ãŠ
ãæçµçã«ã©ã®ããã«æ©èœããããåŠã¶ããšã§ãã çµæã®ã¢ãžã¥ãŒã«ã®ã¢ãŒããã¯ãã£ã¯ãããã»ã¹äžã«å€§ããæ±ºå®ãããŸããã
Promiseãšã¯äœã§ããïŒ
Promiseã¯ç¹å¥ãªãªããžã§ã¯ãã§ãããäœæããããš
ä¿çç¶æ
ã«ãªããŸãïŒ0ã«çãã宿°ã«ããŸãïŒã
次ã«ããªããžã§ã¯ãã¯ãäœææã«ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ããã颿°ã®å®è¡ãéå§ããŸãã 颿°ãæž¡ãããªãã£ãå Žå-ES6æšæºã«åŸã£ãŠã
åŒæ°ãã¹ããŒããå¿
èŠ
ãããã®ã¯é¢æ°ã®äŸå€ã§
ã¯ãããŸãã ã ãã ããJavaå®è£
ã§ã¯ãäœãæããããšãã§ããããªããžã§ã¯ãããçŸç¶ã®ãŸãŸãäœæããããšãã§ããŸãïŒãã®åŸã远å ã®ããžãã¯ã远å ããŸããããã«ã€ããŠã¯åŸã§èª¬æããŸãïŒã
ãããã£ãŠãã³ã³ã¹ãã©ã¯ã¿ãŒã¯é¢æ°ãåãå
¥ããŸãã ãšã³ãžã³ã§ã¯ãããã¯callã¡ãœãããå®è£
ããFunctionã¯ã©ã¹ã®ãªããžã§ã¯ãã§ãã ãã®ã¡ãœããã䜿çšãããšãå®è¡ã³ã³ããã¹ããåŒæ°ãæã€ãã¯ãã«ãããã³åŒã³åºãã¢ãŒãïŒã³ã³ã¹ãã©ã¯ã¿ãŒãŸãã¯éåžžã¢ãŒããšããŠã®åŒã³åºãïŒãå®çŸ©ããããŒã«ãã©ã¡ãŒã¿ãŒã䜿çšããŠã颿°ãåŒã³åºãããšãã§ããŸãã
ããã«ããã®é¢æ°ã¯ãªããžã§ã¯ãã®ãã£ãŒã«ãã«æžã蟌ãŸããåŒã³åºãããšãã§ããŸãã
public static int PENDING = 0; public static int FULFILLED = 1; public static int REJECTED = 2; ... private int state = 0; private Function func;
åæã«ãããã§ã¯ãæ®ãã®2ã€ã®ç¶æ
ã®å®æ°ãšããªããžã§ã¯ãã®çŸåšã®ç¶æ
ãæ ŒçŽããintãã£ãŒã«ããäœæããŸãã
ãã®ãããæšæºã«åŸã£ãŠãå®è¡äžã®é¢æ°ã¯2ã€ã®é¢æ°ã®ãããããåŒã³åºãããšãã§ããŸãïŒæåã®2ã€ã®åŒæ°ãšããŠæž¡ããããããé©åãªæ¹æ³ã§é¢æ°ã·ã°ããã£ã§ååãæå®ããå¿
èŠããããŸãïŒã éåžžãç°¡åã«ããããã«è§£æ±ºãæåŠãªã©ã®æ¹æ³ã䜿çšããŸãã
ãããã¯JavaScriptã®èгç¹ããã¯éåžžã®é¢æ°ã§ããã€ãŸããFunctionãªããžã§ã¯ãã¯ãšã³ãžã³ã®èгç¹ããã®ãã®ã§ãã ãããã«ããã£ãŒã«ãã远å ããŸãã
public Function onFulfilled = null; public Function onRejected = null;
ãããã®é¢æ°ã¯ãã¡ã€ã³ã®äœæ¥é¢æ°ã«ãã£ãŠãã€ã§ãåŒã³åºãããšãã§ããŸããã€ãŸãããã®ã¹ã³ãŒãå
ã«ãªããã°ãªããŸããã ããã«ãäœæ¥ã
çµãããšããªããžã§ã¯ãã®ç¶æ
ããããã
å®çŸããã³
æåŠã«å€æŽããå¿
èŠããããŸãã ç§ãã¡ã®é¢æ°ã¯ãããã¹ã«ã€ããŠäœãç¥ããŸããïŒç¥ã£ãŠã¯ãããŸããïŒã ãããã£ãŠããããã«ã€ããŠèªèããç¶æ
ã®å€æŽãéå§ã§ããäžçš®ã®ã©ãããŒãäœæããå¿
èŠããããŸãã
ãŸãããªããžã§ã¯ãã«setStateïŒïŒã¡ãœãããå¿
èŠã§ãïŒè¿œå ã®ãã§ãã¯ãå¿
èŠã§ããããšãã°ãç¶æ
ãæ¢ã«
æºããããŠããã
æåŠãããŠããå Žåãç¶æ
ã倿Žããæš©å©ã¯ãããŸããïŒã
ãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãæ±ããŸãããïŒ
public Promise(Function f) { func = f; onFulfilled = new PromiseHandleWrapper(this, null, Promise.FULFILLED); onRejected = new PromiseHandleWrapper(this, null, Promise.REJECTED); if (f != null) { Vector<JSValue> args = new Vector<JSValue>(); args.add(onFulfilled); args.add(onRejected); func.call(null, args, false); } }
ããã§ã¯ãã¹ãŠãæãããªããã§ãã 颿°ãæž¡ãããå Žåãããã«åŒã³åºãå¿
èŠããããŸãã ããã§ãªãå Žåã¯ããŸã äœãããŠããŸããïŒãããŠããªããžã§ã¯ãã¯
ä¿çç¶æ
ãä¿æããŠããŸãïŒã
次ã«ããããã®ãã³ãã©ãŒèªäœãã€ã³ã¹ããŒã«ããããšã«ã€ããŠèª¬æããŸãïŒçµå±ãã¡ã€ã³é¢æ°ã§ã¯ãååãæ£åŒãªãã©ã¡ãŒã¿ãŒãšããŠå®£èšããã ãã§ãïŒã ãã®æšæºã«ã¯ãPromise.thenïŒè§£æ±ºãæåŠïŒãPromise.thenïŒè§£æ±ºïŒïŒPromise.thenïŒè§£æ±ºãnullïŒãšåçïŒãPromise.catchïŒæåŠïŒïŒPromise.thenïŒnullãrejectïŒãšåçïŒã®3ã€ã®ãªãã·ã§ã³ãçšæãããŠããŸãïŒïŒã
then颿°ã«é¢ããŠã¯ã2ã€ã®åŒæ°ã詳现ã«äœ¿çšããŠã¡ãœãããå®è£
ããæ®ãã®2ã€ããã·ã§ãŒãã«ããããšããŠäœæããããšãæåã§ããããšã¯æããã§ãã ã ããç§ãã¡ã¯ããïŒ
public Promise then(Function f1, Function f2) { if (state == Promise.FULFILLED || state == Promise.REJECTED) { onFulfilled = new PromiseHandleWrapper(this, f1, Promise.FULFILLED); onRejected = new PromiseHandleWrapper(this, f2, Promise.REJECTED); onFulfilled.call(null, new Vector<JSValue>(), false); return this; } ... onFulfilled = new PromiseHandleWrapper(this, f1, Promise.FULFILLED); onRejected = new PromiseHandleWrapper(this, f2, Promise.REJECTED); if (func != null) { String name1 = func.getParamsCount() > 0 ? func.getParamName(0) : "resolve"; String name2 = func.getParamsCount() > 1 ? func.getParamName(1) : "reject"; func.injectVar(name1, onFulfilled); func.injectVar(name2, onRejected); } if (f1 != null) has_handler = true; if (f2 != null) has_error_handler = true; return this; }
æåŸã«ããªã³ã¯ãèªåèªèº«ã«è¿ããŸããããã¯ãå°æ¥ã®ææãªãã§ãŒã³ã®å®è£
ã«å¿
èŠã§ãã
ã¡ãœããã®æåã«ã©ã®ãããã¯ããããŸããïŒ ãã ããå®éã«ãã³ãã©ãå®è¡ã§ããã®ã¯ãããããæåã«åŒã³åºããåã§ããããŸãïŒããã¯èµ·ãããŸãããããã¯å®å
šã«æ£åžžã§ãïŒã ãã®å Žåãããã«ã¡ãœããã«æž¡ããããã³ãã©ãŒããç®çã®ãã³ãã©ãŒãåŒã³åºãå¿
èŠããããŸãã
çç¥èšå·ã®ä»£ããã«ãããå°ãåŸã«å¥ã®ã³ãŒãããããŸãã
次ã¯ãå¿
é ãã£ãŒã«ããžã®ãã³ãã©ãŒã®ã€ã³ã¹ããŒã«ã§ãã
ãããŠããããæãè峿·±ãéšåã§ãã äœæ¥é¢æ°ã®å®è¡ã«æéãããããšä»®å®ããŸãïŒãããã¯ãŒã¯çµç±ã®ãªã¯ãšã¹ãããŸãã¯ã±ãŒã¹ã¹ã¿ãã£ã®å Žåã¯åã«setTimeoutïŒã ãã®å Žåãåºæ¬çã«ã¯å®è¡ãããŸãããåŸã§ã³ãŒããå®è¡ãã倿°ã®ãªããžã§ã¯ãïŒã¿ã€ããŒããããã¯ãŒã¯XmlHttpRequestã€ã³ã¿ãŒãã§ã€ã¹ãªã©ïŒãäœæãããŸãã ãããŠããããã®ãªããžã§ã¯ãã¯é¢æ°ã®ã¹ã³ãŒãã«ã¢ã¯ã»ã¹ã§ããŸãïŒ
ãããã£ãŠãå¿
èŠãªå€æ°ãã¹ã³ãŒãã«è¿œå ããã®ã«ãŸã æé
ãã§ã¯ãªããããããŸããïŒæé
ãã®å Žåãã³ãŒãã¯ã¡ãœããã®å
é ã§å®è¡ãããŸãïŒã ãããè¡ãã«ã¯ãFunctionã¯ã©ã¹ã§æ°ããã¡ãœãããäœæããŸãã
public void injectVar(String name, JSValue value) { body.scope.put(name, value); } public void removeVar(String name) { body.scope.remove(name); }
å®éã«ã¯ã2çªç®ã®æ¹æ³ã¯å¿
èŠãããŸãããå®å
šæ§ã®ããã«äœæããããã®ã§ãã
次ã¯ãã·ã§ãŒãã«ãããå®è£
ãããšãã§ãã
public Promise then(Function f) { return then(f, null); } public Promise _catch(Function f) { return then(null, f); }
catchã¯javaã®äºçŽèªã§ãããããã¢ã³ããŒã¹ã³ã¢ã远å ããå¿
èŠããããŸããã
次ã«ãsetStateã¡ãœããã«ã€ããŠèª¬æããŸãã æåã®è¿äŒŒã§ã¯ã次ã®ããã«ãªããŸãã
public void setState(int value) { if (this.state > 0) return; this.state = value; }
ããŠããã³ãã©ãŒãããããæ£ç¢ºã«ã¯ããã®äžã®ã©ãããŒããç¶æ
ã倿Žã§ããŸãã ã©ãããŒããã£ãŠã¿ãŸãããïŒ
public class PromiseHandleWrapper extends Function { public PromiseHandleWrapper(Promise p, Function func, int type) { this.promise = p; this.func = func; this.to_state = type; } @Override public JSValue call(JSObject context, Vector<JSValue> args, boolean as_constr) { return call(context, args); } @Override public JSValue call(JSObject context, Vector<JSValue> args) { JSValue result; if (func != null) { Block b = getCaller(); if (b == null) { b = func.getParentBlock(); while (b.parent_block != null) { b = b.parent_block; } } func.setCaller(b); result = func.call(context, args, false); } else { result = Undefined.getInstance(); } promise.setResult(result); promise.setState(to_state); return promise.getResult(); } @Override public JSError getError() { return func.getError(); } private Promise promise; private Function func; private int to_state = 0; }
ã©ãããŒã«ã¯2ã€ã®ã¿ã€ãããããŸãããã¯ã©ã¹ã¯1ã€ã§ãã ãŸããæŽæ°ãã£ãŒã«ãto_stateãã¿ã€ããæ
åœããŸãã ããã¯æªããªãããã§ã:)
ã©ãããŒã«ã¯ããã®æ©èœãšãã®çŽæã®äž¡æ¹ãžã®ãªã³ã¯ããããŸãã ããã¯éåžžã«éèŠã§ãã
ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãã¹ãŠãæç¢ºã«ãªã£ãã®ã§ã颿°ã¯ã©ã¹ã®ã¡ãœããããªãŒããŒã©ã€ãããåŒã³åºãã¡ãœãããèŠãŠã¿ãŸãããã JSã€ã³ã¿ãŒããªã¿ãŒã®å Žåãã©ãããŒã«ã¯åã颿°ããããŸããã€ãŸããåŒã³åºããããå€ãååŸãããã§ãããåãã€ã³ã¿ãŒãã§ãŒã¹ãæã€ãªããžã§ã¯ãã§ãã
ãŸããã©ãããŒã颿°ã«åŒã³åºããããšãã«åãåã£ãCallerãªããžã§ã¯ããã¹ããŒããå¿
èŠããããŸããããã¯ãå°ãªããšãæ£ããäŸå€ããããã¢ããããããã«å¿
èŠã§ãã
次ã«ã颿°ãåŒã³åºãããã®å®è¡çµæããã£ãŒã«ãã«ä¿åããŸãã åæã«ãpromisãªããžã§ã¯ãã«èšå®ããããã«å¥ã®setResultã¡ãœãããäœæããŸãïŒ
public JSValue getResult() { return result; } public void setResult(JSValue value) { result = value; }
æåŸã®è¡ã«ã€ããŠã¯ãŸã 説æããŸãããããã¯é£éã«å¿
èŠã§ãã æãäºçްãªã±ãŒã¹ã§ã¯ãåä¿¡ããã³éä¿¡ããå€ãšåãå€ãããã«è¿ãããŸãã
éèŠãªç¹ïŒäœæ¥é¢æ°ã¯ãthenãŸãã¯catchã¡ãœãããåŒã³åºãåã«ãresolveãŸãã¯rejectãåŒã³åºãããšãã§ããŸãïŒãŸãã¯ããŸã£ããåŒã³åºããªãå ŽåããããŸãïŒã äŸå€ãæããªãããã«ããããã¹ãäœæãããšãã«ããã³ãã©ãŒé¢æ°ãæããªã2ã€ã®ãããã©ã«ããã©ãããŒãäœæããŸãã åŒã³åºããããšãã圌ãã¯ç§ãã¡ã®çŽæã®ç¶æ
ã倿Žããã ãã§ãïŒãããŠåŒã³åºããããšããããã¯èæ
®ãããŸãïŒã
远ããããçŽæ
èŠããã«ã远跡ã¯p.thenïŒf1ãf2ïŒ.thenïŒf3ãf4ïŒ.catchïŒf5ïŒã®ãããªãã®ãæžãèœåã§ãã
ãã®ãããthenã¡ãœãããš_catchã¡ãœããã¯Promiseãªããžã§ã¯ããè¿ããŸãã
æšæºãæåã«äŒããããšã¯ãthenã¡ãœããã¯ãæ¢åã®ãã³ãã©ãŒãããå Žåãæ°ãããããã¹ãäœæããŠãã§ãŒã³ã«è¿œå ããå¿
èŠããããšããããšã§ãã çŽæã¯äºãã«çãããªããã°ãªããªãã®ã§ãç·åœ¢ãªã¹ããä¿åããäž»èŠãªçŽæãæããªãããã«ããŸããåçŽæã¯ã以äžãžã®ãªã³ã¯ã®ã¿ãä¿åããŸãïŒæåã¯nullã§ãïŒã
public Promise then(Function f1, Function f2) { if (state == Promise.FULFILLED || state == Promise.REJECTED) { onFulfilled = new PromiseHandleWrapper(this, f1, Promise.FULFILLED); onRejected = new PromiseHandleWrapper(this, f2, Promise.REJECTED); onFulfilled.call(null, new Vector<JSValue>(), false); return this; } if (has_handler || has_error_handler) { if (next != null) { return next.then(f1, f2); } Promise p = new Promise(null); p.then(f1, f2); next = p; return p; } onFulfilled = new PromiseHandleWrapper(this, f1, Promise.FULFILLED); onRejected = new PromiseHandleWrapper(this, f2, Promise.REJECTED); if (func != null) { String name1 = func.getParamsCount() > 0 ? func.getParamName(0) : "resolve"; String name2 = func.getParamsCount() > 1 ? func.getParamName(1) : "reject"; func.injectVar(name1, onFulfilled); func.injectVar(name2, onRejected); } if (f1 != null) has_handler = true; if (f1 != null) has_error_handler = true; return this; } ... private Promise next = null;
äžè¶³ããŠãããããã¯ã¯æ¬¡ã®ãšããã§ãããã§ã«æ¬¡ã®çŽæãããå ŽåãåŒã³åºãã圌ã«è»¢éããŠçµäºããŸãïŒå¿
èŠã«å¿ããŠãåœŒã¯æåŸãŸã§è»¢éããŸãïŒã ãããŠãååšããªãå Žåã¯ãã¡ãœããã§åãåã£ããã³ãã©ãŒãäœæããŠå²ãåœãŠããã®åŸããããæ¢ã«è¿ããŸãã ãã¹ãŠãã·ã³ãã«ã§ãã
次ã«ãsetStateã¡ãœãããçµäºããŸãã
public void setState(int value) { if (this.state > 0) return; this.state = value; Vector<JSValue> args = new Vector<JSValue>(); if (result != null) args.add(result); if (value == Promise.FULFILLED && next != null) { if (onFulfilled.getError() == null) { if (result != null && result instanceof Promise) { ((Promise)result).then(next.onFulfilled, next.onRejected); next = (Promise)result; } else { result = next.onFulfilled.call(null, args, false); } } else { args = new Vector<JSValue>(); args.add(onFulfilled.getError().getValue()); result = next.onRejected.call(null, args, false); } } if (value == Promise.REJECTED && !has_error_handler && next != null) { result = next.onRejected.call(null, args, false); } }
ãŸããæšæºã§ã¯ãåã®çµæã次ã®çŽæã®ããã»ããµã«è»¢éããããšã矩åä»ããããŠããŸãïŒãã§ãŒã³ã®äž»ãªæå³ã¯ãæäœãå²ãåœãŠãŠããã2çªç®ã®æäœãå²ãåœãŠãŠãæåã®çµæãåãå
¥ããããã«ããããšã§ãïŒã
第äºã«ããšã©ãŒã¯ç¹å¥ãªæ¹æ³ã§åŠçãããŸãã æåããçµæããã§ãŒã³ã«æ²¿ã£ãŠïŒå€æŽããŠïŒæåŸã«éä¿¡ããããšããã³ãã©ãŒã³ãŒãã§çºçãããšã©ãŒã¯ãæ¬¡ã®æåŠããããŸã§1ã¹ãããã ãéä¿¡ããããããã§ãŒã³ã®æåŸã«å°éãããšãããã¢ããããŸãã
第äžã«ã颿°ã¯æ°ãããããã¹ãè¿ãããšãã§ããŸãã ãã®å Žåãæ¬¡ã®ãã®ãæ¢ã«èšå®ãããŠããå Žåãæ¢åã®ãã³ãã©ãã¹ããŒããããšã«ãããæ¬¡ã®ãã®ã眮ãæããå¿
èŠããããŸãã ããã«ãããã€ã³ã¹ã¿ã³ãå®è¡ãã³ãã©ãŒãšéåæãã³ãã©ãŒã®çµã¿åãããå¯èœã«ãªãããããèªäœãPromiseãè¿ããŸãã
äžèšã®ã³ãŒãã¯ãããããã¹ãŠã®ã·ããªãªã«å¯Ÿå¿ããŠããŸãã
æåã®ãã¹ã
JSParser jp = new JSParser("function cbk(str) { \"Promise fulfilled: \" + str } function f(resolve, reject) { setTimeout(function() { resolve(\"OK\") }, 1500) }"); System.out.println(); System.out.println("function cbk(str) { \"Promise fulfilled: \" + str }"); System.out.println("function f(resolve, reject) { setTimeout(function() { resolve(\"OK\") }, 1500) }"); System.out.println(); Expression exp = Expression.create(jp.getHead()); exp.eval(); jsparser.Function f = (jsparser.Function)Expression.getVar("f", exp); f.setSilent(true); jsparser.Promise p = new jsparser.Promise(f); p.then((jsparser.Function)Expression.getVar("cbk", exp));
ãããŸã§ããã¹ãŠãJavaã³ãŒãã§ç®¡çããŠããŸããã ããã«ããããããããã¹ãŠããã§ã«æ©èœããŠããŸãã1ç§åã§ãã³ã³ãœãŒã«ã«ãçŽæãæºããããŸããïŒOKããšããç¢æã衚瀺ãããŸãã ãšããã§ãPromiseã®ã¯ãŒãã³ã°é¢æ°ãããã§ãŒã³ãªãã§åŒã³åºãããè§£æ±ºé¢æ°ãšæåŠé¢æ°ã¯ãä»»æã®æ°ã®åŒæ°ãåãããšãã§ããŸãã ãšãŠã䟿å©ã§ãã ãã®äŸã§ã¯ãæååãOKããæž¡ããŸããã
å¥ã®å°ããªã³ã¡ã³ãïŒãã§ãŒã³äžã«äœæããããããã¹ã«ã¯ãååãšããŠæ©èœããæ©èœã¯ãããŸããã åã®ãããã¹ã®ç¶æ
ãå€åãããšãããã«ãã³ãã©ãŒãåŒã³åºããŸãã
äŸã¯ãã£ãšè€éã§ãïŒ
JSParser jp = new JSParser("function cbk1(str) { \"Promise 1 fulfilled: \" + str; return str } " + "function cbk2(str) { setTimeout(str => { \"Promise 2 fulfilled: \" + str }, 1000); throw \"ERROR\" } " + "function cbk3(str) { \"Promise 3 fulfilled: \" + str; return str } " + "function err(str) { \"An error has occured: \" + str } " + "function f(resolve, reject) { setTimeout(function() { resolve(\"OK\") }, 300) }"); System.out.println(); System.out.println("function cbk1(str) { \"Promise 1 fulfilled: \" + str; return str }"); System.out.println("function cbk2(str) { setTimeout(str => { \"Promise 2 fulfilled: \" + str }, 1000); throw \"ERROR\" }"); System.out.println("function cbk3(str) { \"Promise 3 fulfilled: \" + str; return str }"); System.out.println("function err(str) { \"An error has occured: \" + str }"); System.out.println("function f(resolve, reject) { setTimeout(function() { resolve(\"OK\") }, 300) }"); System.out.println("(new Promise(f)).then(cbk1).then(cbk2).then(cbk3, err)"); System.out.println(); Expression exp = Expression.create(jp.getHead()); ((jsparser.Function)Expression.getVar("f", exp)).setSilent(true); ((jsparser.Function)Expression.getVar("cbk2", exp)).setSilent(true); exp.eval(); jsparser.Function f = (jsparser.Function)Expression.getVar("f", exp); f.setSilent(true); jsparser.Promise p = new jsparser.Promise(f); p.then((jsparser.Function)Expression.getVar("cbk1", exp)) .then((jsparser.Function)Expression.getVar("cbk2", exp)) .then((jsparser.Function)Expression.getVar("cbk3", exp), (jsparser.Function)Expression.getVar("err", exp));
ãã®äŸãåŒã³åºããšã次ã®åºåãåŸãããŸãã
{}
"Promise 1 fulfilled: OK"
"OK"
"An error has occured: ERROR"
undefined
"Promise 2 fulfilled: OK"
æåã®äžæ¬åŒ§ã¯ããã§ãŒã³ã®çµæãšããŠã³ãŒã«ã®ãã§ãŒã³ãè¿ãããpromiseãªããžã§ã¯ãã§ãã cbk1颿°ã§ã¯ããOKããè¿ããŸããããã®å€ã¯cbk2ã«æž¡ãããæåŸã®è¡ã«è¡šç€ºãããŠããŸãã cbk2ã®å
éšã§ã¯ãå€ãERRORãã®ãšã©ãŒãã¹ããŒããŸãããããã£ãŠãcbk3ã¯å®è¡ãããŸããããerrãå®è¡ãããŸãïŒãã§ãŒã³å
ã®åã®promiseã®ãã³ãã©ãŒã§ãšã©ãŒãçºçããå ŽåïŒã ãããããã®ã³ãŒãã¯å³åº§ã«å®è¡ãããŸãããcbk2ã®åºåã¯ã¿ã€ããŒã«æããããè£å©é¢æ°ãä»ããŠè¡ãããŸãã å¿
èŠã«å¿ããŠstr倿°ã«ã¢ã¯ã»ã¹ã§ããŸãããåºåã¯ä»¥äžã®ãšããã§ãã ãã®äŸãChrome 49ã§å®è¡ãããšã1ã€ã®äŸå€ãé€ããŠãŸã£ããåãåºåãåŸãããŸãã倿°strã¯ãsetTimeoutã«æž¡ãããå¿å颿°ã§ã¯è¡šç€ºãããŸããã ããã¯ãChromeã®ç¢å°é¢æ°ã®åäœã®ç¹åŸŽã§ãïŒãããŠãããããæšæºã«åŸã£ãŠéåžžã«å¿
èŠã§ããããã§ã¯ãåé¡ãäœã§ããããèšãã®ãé£ãããšæããŸãïŒã ç¢å°é¢æ°ãéåžžã®é¢æ°ã«å€æŽãããšãåºåã¯åãã«ãªããŸãã
Javascript probros
ããããããã ãã§ã¯ãããŸããã ç§ãã¡ã®æçµçãªç®æšã¯ãã€ã³ã¿ãŒããªã¿ãŒã«ãã£ãŠå®è¡ãããJSã³ãŒããæ°ããæ©èœã䜿çšããããšã§ãã ããããããã¯ãã§ã«æè¡ã®åé¡ã§ãã
ã³ã³ã¹ãã©ã¯ã¿ãŒãäœæããŸãã
public class PromiseC extends Function { public PromiseC() { items.put("prototype", PromiseProto.getInstance()); PromiseProto.getInstance().set("constructor", this); } @Override public JSValue call(JSObject context, Vector<JSValue> args, boolean as_constr) { return call(context, args); } @Override public JSValue call(JSObject context, Vector<JSValue> args) { if (args.size() == 0) return new Promise(null); if (!args.get(0).getType().equals("Function")) { JSError e = new JSError(null, "Type error: argument is not a function", getCaller().getStack()); getCaller().error = e; return new Promise(null); } return new Promise((Function)args.get(0)); } }
ãããŠãå¿
èŠãªã¡ãœããã®ã»ãããæã€ãããã¿ã€ããªããžã§ã¯ãïŒ
public class PromiseProto extends JSObject { class thenFunction extends Function { @Override public JSValue call(JSObject context, Vector<JSValue> args, boolean as_constr) { if (args.size() == 1 && args.get(0).getType().equals("Function")) { return ((Promise)context).then((Function)args.get(0)); } else if (args.size() > 1 && args.get(0).getType().equals("Function") && args.get(1).getType().equals("Function")) { return ((Promise)context).then((Function)args.get(0), (Function)args.get(1)); } else if (args.size() > 1 && args.get(0).getType().equals("null") && args.get(1).getType().equals("Function")) { return ((Promise)context)._catch((Function)args.get(1)); } return context; } } class catchFunction extends Function { @Override public JSValue call(JSObject context, Vector<JSValue> args, boolean as_constr) { if (args.size() > 0 && args.get(0).getType().equals("Function")) { return ((Promise)context)._catch((Function)args.get(0)); } return context; } } private PromiseProto() { items.put("then", new thenFunction()); items.put("catch", new catchFunction()); } public static PromiseProto getInstance() { if (instance == null) { instance = new PromiseProto(); } return instance; } @Override public void set(JSString str, JSValue value) { set(str.getValue(), value); } @Override public void set(String str, JSValue value) { if (str.equals("constructor")) { super.set(str, value); } } @Override public String toString() { String result = ""; Set keys = items.keySet(); Iterator it = keys.iterator(); while (it.hasNext()) { if (result.length() > 0) result += ", "; String str = (String)it.next(); result += str + ": " + items.get(str).toString(); } return "{" + result + "}"; } @Override public String getType() { return type; } private String type = "Object"; private static PromiseProto instance = null; }
ãã¹ãŠãæ©èœããããã«ãæåã«Promiseã³ã³ã¹ãã©ã¯ã¿ãŒã«1è¡è¿œå ããããšãå¿ããªãã§ãã ããã
public Promise(Function f) { items.put("__proto__", PromiseProto.getInstance()); ... }
ãããŠããã¹ããå°ã倿ŽããŸãã
JSParser jp = new JSParser("function cbk1(str) { \"Promise 1 fulfilled: \" + str; return str } " + "function cbk2(str) { setTimeout(str => { \"Promise 2 fulfilled: \" + str }, 1000); throw \"ERROR\" } " + "function cbk3(str) { \"Promise 3 fulfilled: \" + str; return str } " + "function err(str) { \"An error has occured: \" + str } " + "function f(resolve, reject) { setTimeout(function() { resolve(\"OK\") }, 300) }; " + "(new Promise(f)).then(cbk1).then(cbk2).then(cbk3, err)"); System.out.println(); System.out.println("function cbk1(str) { \"Promise 1 fulfilled: \" + str; return str }"); System.out.println("function cbk2(str) { setTimeout(str => { \"Promise 2 fulfilled: \" + str }, 1000); throw \"ERROR\" }"); System.out.println("function cbk3(str) { \"Promise 3 fulfilled: \" + str; return str }"); System.out.println("function err(str) { \"An error has occured: \" + str }"); System.out.println("function f(resolve, reject) { setTimeout(function() { resolve(\"OK\") }, 300) }"); System.out.println("(new Promise(f)).then(cbk1).then(cbk2).then(cbk3, err)"); System.out.println(); Expression exp = Expression.create(jp.getHead()); ((jsparser.Function)Expression.getVar("f", exp)).setSilent(true); ((jsparser.Function)Expression.getVar("cbk2", exp)).setSilent(true); exp.eval(); jsparser.Function f = (jsparser.Function)Expression.getVar("f", exp); f.setSilent(true);
çµè«ã¯å€ãããªãã¯ãã§ãã
ããã ãã§ãïŒ ãã¹ãŠãæ£åžžã«æ©èœãã远å ã®åäœãã¹ããèšè¿°ããŠãçºçããå¯èœæ§ã®ãããšã©ãŒãæ€çŽ¢ã§ããŸãã
ãã®ã¡ã«ããºã ãJavaã«é©å¿ãããæ¹æ³ã¯ïŒ ãšãŠãç°¡åã§ãã 颿°ã«äŒŒãã¯ã©ã¹ãäœæããoperateã¡ãœããã§äœããè¡ããŸãã ãããŠããã§ã«ã©ãããŒã§ã©ããããŠããŸãã ãããã«ããããã®ããŒãã«ã¯ããããã®çŽ æŽããããã¿ãŒã³ããããŸãã
ãã®èšäºã誰ãã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã ãšã³ãžã³ãœãŒã¹ãæãã€ãããããã«æçš¿ããäžè¶³ããŠããæ©èœã远å ããŸãã è¯ãäžæ¥ãïŒ