isMounted
ã¯ES6ã¯ã©ã¹ã§ã¯ãã§ã«å©çšã§ãããåé€ããå¯èœæ§ããããšããèŠåããã§ã«è¡šç€ºãããŠããŸãããå®éã«ã¯éæšå¥šã«ããgithubã®åé¡ã¯ãããŸããã ä»æ¥ã®è°è«ã«ãããšãç§ãã¡ã¯åºæ¬çã«ã isMounted
ããé¢ããŠããããå»æ¢ããããšã«åæããŠããŸãã çŽæïŒããã³é¢é£ãããŠãŒã¹ã±ãŒã¹ïŒã«é¢ããããã€ãã®è¯ã話ãç解ããå¿
èŠããããŸãã
ãã®åé¡ã¯ããã®ç®æšã«åããé²æç¶æ³ã远跡ããããšã§ãã
èæ¯ã«ã€ããŠã¯ã以äžããèªã¿ãã ããã
ç§ã¯ããã«åæããŸããã ç¹ã«ES6Promiseã¯componentWillUnmount
ã§ç¢ºå®ã«ãã£ã³ã»ã«ã§ããªããããsetStateãŸãã¯å¥ã®ã¢ã¯ã·ã§ã³ã®åã«ã³ã³ããŒãã³ããããŠã³ããããŠãããã©ããã確èªããå¯äžã®æ¹æ³ãåé€ãããšãéåæãã°ã远跡ããã®ãé£ããå€ãã®æ¹æ³ãéãããŸãã
@yaycmykãããã£ãŠã次ã®è¡ã«ãªããŸãã
çŽæïŒããã³é¢é£ãããŠãŒã¹ã±ãŒã¹ïŒã«é¢ããããã€ãã®è¯ã話ãç解ããå¿ èŠããããŸãã
ç¹ã«ãç§ããªã¹ãããèæ¯ã®åé¡ãèªãã§ãã ããïŒ https ïŒ
ã³ã¡ã³ããèªã¿ãŸããã ç§ã¯åé¡ãæã«è² ããªãããšã«æ°ã¥ããŸããã
ãªãçŽæã¯ç¢ºå®ã«åãæ¶ãããªãã®ã§ããïŒ ãœãŒã¹/蚌æ/äŸã¯ãããŸããïŒ
2015幎11æ16æ¥æææ¥ãEvanJacobsã®[email protected]ã¯æ¬¡ã®ããã«æžããŠããŸãã
ç§ã¯ããã«åæããŸããã ES6ã®çŽæã¯ç¹ã«ç¢ºå®ã§ã¯ãããŸãã
componentWillUnmountã§ãã£ã³ã»ã«ãããããã次ã®ããšã確èªããå¯äžã®æ¹æ³ãåé€ããŸãã
setStateãŸãã¯å¥ã®ã¢ã¯ã·ã§ã³ãéãåã«ã³ã³ããŒãã³ããããŠã³ããããŸã
éåæã®ãã°ã远跡ããã®ãé£ããå€ãã®æ¹æ³ã
@ nvartolomeiES6ã®çŽæã®ä»æ§ãèŠãŠãã ããã
ããã¯é·æçãªç®æšã§ãããããã«èµ·ãã£ãŠããããšã§ã¯ãããŸããã ãã ããèšç»ãšãã£ã¹ã«ãã·ã§ã³ã1ãæã§è¿œè·¡ãããããçºçãããšãã«ãã¹ãŠã®åé¡ã®ã³ã¡ã³ãã«ãŸããã£ãŠè¿œè·¡ããã®ã§ã¯ãããŸããã PromisesãçŸåšãã£ã³ã»ã«ã§ããªããšããåé¡ãèªèããŠããŸãããããããŸã ãããè¡ã£ãŠããªãäž»ãªçç±ã§ãã
@yaycmykéåžžã«è€éãªåé¡ãé床ã«åçŽåããããã«...ã³ã¡ã³ãã¯èšã£ãŠããŸã...ããŠã³ããããŠããªãã³ã³ããŒãã³ãã«setState
ã䜿çšããŠisMounted
ã䜿çšããŠãã setState
ãšããåé¡ã¯å®éã«ã¯è§£æ±ºãããŸããsetState
ãåŒã³åºãããšã¯ããã¹ãã«å¿
ããã衚瀺ãããªã競åç¶æ
ãåŒãèµ·ããå¯èœæ§ãããããããšã«ããã¢ã³ããã¿ãŒã³ã®ãããã§ãã ãããã£ãŠãç§ãã¡ã¯ãããåãé€ããReactã§promiseã䜿çšããããã®ããã¹ããã©ã¯ãã£ã¹ãã®æšå¥šäºé
ãç解ããããšæããŸãã
åé¡ãå°ãäžå¯è§£ã§ããããšã«åæããŸãããããã¯äž»ã«ãç§ãã¡ããŸã ç解ããŠããè€éãªåé¡ã§ããããŸã å®åçãªå¯Ÿå¿ããªãããã§ãã
promiseã®çµæãšããŠsetStateãåŒã³åºãããšã¯ããã¹ãã«å¿ ããã衚瀺ãããªã競åç¶æ ãåŒãèµ·ããå¯èœæ§ãããããããšã«ããã¢ã³ããã¿ãŒã³ã®ãããã§ãã
ç§ãã¡ã¯ããã«åæããªãããšã«åæããããšãã§ããŸãã ã³ã³ãã³ããéåæã§ãã§ãããããŠããã解決ãããã³ã³ãã³ãããããããããã«ãã«ã¹ã±ãŒã«ã®åã¬ã³ããªã³ã°ãå®è¡ããå¿ èŠããªãå ŽåããããŸãã ç¹ã«ãå®å šãªä»®æ³åã¬ã³ããªã³ã°ãäžèŠãªç¡éããŒãã«ãã¥ãŒã®å®è£ ã§äœ¿çšããŸãã
promiseããã£ã³ã»ã«ã§ããªãå ŽåããããŸããã次ã®ããã«ãã¢ã³ããŠã³ãæã«ã³ã³ããŒãã³ããéåç §ãããããšãã§ããŸãã
const SomeComponent = React.createClass({
componentDidMount() {
this.protect = protectFromUnmount();
ajax(/* */).then(
this.protect( // <-- barrier between the promise and the component
response => {this.setState({thing: response.thing});}
)
);
},
componentWillUnmount() {
this.protect.unmount();
},
});
éèŠãªéãã¯ã this.protect.unmount()
ãcomponentWillUnmount
ã§åŒã³åºãããå Žåããã¹ãŠã®ã³ãŒã«ããã¯ãéåç
§ãããŸããã€ãŸããã³ã³ããŒãã³ããéåç
§ãããpromiseãå®äºãããšãno-opãåŒã³åºãããŸãã ããã«ãããpromiseãããŠã³ããããŠããªãã³ã³ããŒãã³ããåç
§ããããšã«é¢é£ããã¡ã¢ãªãªãŒã¯ãé²ãããšãã§ããŸãã secureFromUnmountã®ãœãŒã¹
ãã®ç°¡åãªæ¹æ³ã䜿çšããŠãä»»æã®çŽæã«ãã£ã³ã»ã«ãè¿œå ã§ããŸã
const makeCancelable = (promise) => {
let hasCanceled_ = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then((val) =>
hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
);
promise.catch((error) =>
hasCanceled_ ? reject({isCanceled: true}) : reject(error)
);
});
return {
promise: wrappedPromise,
cancel() {
hasCanceled_ = true;
},
};
};
ç·šéïŒæ£ç¢ºæ§/å®å šæ§ã®ããã«æŽæ°ãããŸããã
䜿ãæ¹
const somePromise = new Promise(r => setTimeout(r, 1000));
const cancelable = makeCancelable(somePromise);
cancelable
.promise
.then(() => console.log('resolved'))
.catch(({isCanceled, ...error}) => console.log('isCanceled', isCanceled));
// Cancel promise
cancelable.cancel();
ES6ããµããŒãããæ¹æ³ããªã¹ãããããšã§ããããããã£ã³ã»ã«å¯èœã«ããããšã¯éèŠã§ã¯ãããŸããã ç®çã¯ãä»æ§ã®åšå²ã§æ©èœããã®ã§ã¯ãªããä»æ§ã§æ©èœãããœãªã¥ãŒã·ã§ã³ãæäŸããããšã§ãã
åæããŸãã çŽæã®çµæãåãåã£ããšãã«ã³ã³ããŒãã³ãããŸã ããŠã³ããããŠãããã©ãããåã«ç¢ºèªããã®ã§ã¯ãªããããããçš®é¡ã®éæ³ã«é Œããªããã°ãªããŸãããããããã°ãçµæãèšå®ããã¯ãã®ã³ã³ããŒãã³ãããçŽæãããã€ã³ã解é€ãããŠãçŽæã®æ¹æ³ãšæ確ã«æŠãããšãã§ããŸãããã¶ã€ã³ãããã
ç§ã«ã¯ãåçŽãªãã¹ãããããåŠçããæãç°¡åãªæ¹æ³ã§ãããœãªã¥ãŒã·ã§ã³ãéå°ã«èšèšããŠããããã«æããŸãã
次ã®æ¹æ³ã§ç°¡åã«ãã§ãã¯ã§ããŸãã
React.createClass(function() {
componentDidMount: function() {
this._isMounted = true;
ajax(/* */).then(this.handleResponse);
}
handleResponse: function(response) {
if (!this._isMounted) return; // Protection
/* */
}
componentWillUnmount: function() {
this._isMounted = false;
}
});
ããã¯ãã¡ããç§ã®æèŠã§ãããreactã³ã³ããŒãã³ãå ã§promiseã䜿çšããŠéåæããŒã¿ãããŒãããããšã¯éåžžã«äžè¬çãªã·ããªãªã§ãããããç¬èªã®å®åã³ãŒããäœæããã®ã§ã¯ãªããreactã§ã«ããŒããå¿ èŠããããŸãã
åé¡ã¯ãçã®ããŠã³ãç¶æ ãèš±å¯ããã«ã¯ãreactãåã³ã³ããŒãã³ãã§DOMããŠã³ãããã»ã¹ãçµäºãããšãã«ãªã¹ããŒãè¿œå ããå¿ èŠãããããšã§ãïŒåããå®çŸ©ãããŠããå Žåã¯componentDidMountãã¢ã¿ããããŸãïŒããå¿ èŠããªããããperfã«åœ±é¿ããŸãã©ãã§ããããäŒãããã«ã componentDidMountã¯æªå®çŸ©ã§ãããããã³ã³ããŒãã³ãã¯ããã©ã«ãã§DOMããŠã³ãã®æºåãã§ããŠããããšããªãã¹ã³ããŸããã
setState
ã«ãç®çã®ç¶æ
å€åã«è§£æ±ºãããé£éãããã¹ãæž¡ãããšãã§ãããšãããã©ãã§ããããã ã³ã³ããŒãã³ããã¢ã³ããŠã³ããããä¿çäžã®ãããã¹ãããå Žåããããã®æçµçãªçµæã¯ç¡èŠãããŸãã
@istarkovçŽ æµãªãã¿ãŒã³ãããã®ããã«ïŒ å°ãå€æŽãããAPIã¯æ¬¡ã®ãšããã§ãã
// create a new promise
const [response, cancel] = await cancelable(fetch('/api/data'));
// cancel it
cancel();
ç§ã¯Reactãšããã¥ã¡ã³ããèªãã®ãåããŠãªã®ã§ããããæšãŠãã ãã§ããAjaxãä»ããåæããŒã¿ã®.isMounted()
ã䜿çšãããããWebãµã€ãã¯Webãµã€ããšäžèŽããŸããã äžèšã®@istarkovã®ãã¿ãŒã³ã䜿çšããŠã componentWillUnmount
ã®åæããŒãããã£ã³ã»ã«ããæ¹æ³ã«ã€ããŠã®å®å
šãªãã³ããèŠãã®ã¯çŽ æŽãããããšã§ãã
@dtertman https://github.com/facebook/react/pull/5870ã§ä¿®æ£ãããããã¥ã¡ã³ããå³éžããããšãã«ãªã³ã©ã€ã³ã«ãªããŸãã
@jimfbããããšããæ€çŽ¢ã§ãããã©ã®ããã«éããã®ãããããŸããã
@istarkovã¯ããããæå³çãªãã®ãã©ããã¯makeCancelable
ã¯åŠçããŸããã å
ã®promiseãæåŠãããå Žåããã³ãã©ãŒã¯åŒã³åºãããŸããã
å ã®çŽæã®ãšã©ãŒãåŠçãããå Žåããããããããã¯çæ³çã§ã¯ãªãããã§ãã
ããããå
ã®çŽæã®æåŠãåŠçããmakeCancelable
ç§ã®ææ¡ã§ãã
const makeCancelable = (promise) => {
let hasCanceled_ = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then((val) =>
hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
);
promise.catch((error) =>
hasCanceled_ ? reject({isCanceled: true}) : reject(error)
);
});
return {
promise: wrappedPromise,
cancel() {
hasCanceled_ = true;
},
};
};
ãã£ã³ã»ã«å¯èœãªçŽæãããããšãè¯ãèãã§ãããã©ããã¯ããããŸããããçŽæããã£ã³ã»ã«ã§ããããã«ããå Žåã¯ãåºæ¬çãªåäœãç¶æããå¿ èŠããããŸã:)ã
@vpontis ïŒ+1ïŒ
@istarkovå ã®æçš¿ã¯ããã§åç §ãããŸãïŒ https ïŒ //facebook.github.io/react/blog/2015/12/16/is Mounted-antipattern.html
æçš¿ãæŽæ°ãããã§ããããããšãæçš¿ã®äœæè ã«ã¡ãã»ãŒãžãéä¿¡ããå¿ èŠããããŸããïŒ
@vpontisããããšããä¿®æ£ããŸãïŒ ïŒhttps://github.com/facebook/react/pull/6152ïŒ
ãã@jimfb ãã€ã³ã¿ãŒãããã§ããªãã«
makeCancelable
é¢æ°ã®å¥ã®ãã°ä¿®æ£ïŒæè¿ã®ããŒãããŒãžã§ã³ã§UnhandledPromiseRejectionWarning
ãçºçããå¯èœæ§ããããŸãïŒç¹ã«ãæ°ããããŒãžã§ã³ã®ããŒãã§ãã¹ããå®è¡ããå ŽåïŒã ããŒã6.6.0ã§ã®å€æŽã®1ã€ã¯ãæªåŠçã®promiseæåŠããã¹ãŠèŠåã«ãªãããšã§ãã @vpontisã®æ¢åã®ã³ãŒãã«ã¯ãåãåºæ¬çŽæã§å¥ã
ã®then
ãšcatch
åŒã³åºãããããŸããã äºå®äžãããã«ãã_two_promiseãäœæãããŸãã1ã€ã¯æåã®ã¿ãåŠçãããã1ã€ã¯ãšã©ãŒã®ã¿ãåŠçããŸãã ã€ãŸãããšã©ãŒãçºçããå Žåãæåã®Promiseã¯ããŒãã«ãã£ãŠæªåŠçã®PromiseæåŠãšèŠãªãããŸãã
ä¿®æ£ã¯éåžžã«ç°¡åã§ãã2ã€ã®åŒã³åºãããã§ãŒã³ããã ãã§ãæåãã³ãã©ãŒãšãšã©ãŒãã³ãã©ãŒã®äž¡æ¹ã§1ã€ã®çŽæãã§ããŸãã ä¿®æ£ãããã³ãŒãã¯æ¬¡ã®ãšããã§ãã
const makeCancelable = (promise) => {
let hasCanceled_ = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise
.then((val) =>
hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
)
.catch((error) =>
hasCanceled_ ? reject({isCanceled: true}) : reject(error)
);
});
return {
promise: wrappedPromise,
cancel() {
hasCanceled_ = true;
},
};
};
@alangpierceããã¯æ£è§£ã«éåžžã«è¿ãã§ãããå®å
šã§ã¯ãããŸããã resolve()
ãŸãã¯reject()
ãäœããã®çç±ã§è§£æ±ºãããpromiseã§åæçã«ã¹ããŒãããå Žåãäž¡æ¹ã®ãã³ãã©ãŒãåŒã³åºãããŸãã
解決çã¯ã .then(onFulfilled, onRejected)
ãã¿ãŒã³ã䜿çšããããšã§ãã
const makeCancelable = (promise) => {
let hasCanceled_ = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then(
(val) => hasCanceled_ ? reject({isCanceled: true}) : resolve(val),
(error) => hasCanceled_ ? reject({isCanceled: true}) : reject(error)
);
});
return {
promise: wrappedPromise,
cancel() {
hasCanceled_ = true;
},
};
};
ãã®makeCancelableãœãªã¥ãŒã·ã§ã³ã¯ãisMountedïŒïŒãéæšå¥šã«ãªãçç±ã«ã€ããŠãã€ã³ã3ãèŠããšãã®isMountedïŒïŒåŒã³åºããšå®è³ªçã«åãã§ã¯ãããŸããã
ã³ã³ããŒãã³ããå®å šã«ã¢ã³ããŠã³ãããããšãã«setStateãåŒã³åºããŸãã
ããã¯ãéåæã³ãŒã«ããã¯ãé©åã«ã¯ãªãŒã³ã¢ãããããŠããªãããšã匷ã瀺ããŠããŸãã æ®å¿µãªãããäž»æµã®JS APIã䜿çšãããšããã³ã°ããŠããéåæã³ãŒã«ããã¯ã®ã¯ãªãŒã³ã¢ãããéåžžã«ç°¡åã«åé¿ã§ããŸãã
1ã€ã®ã³ãŒã«ããã¯ã¯å€§ããããšã§ã¯ãããŸããã ãã ãããã®ã³ãŒã«ããã¯ã¯ããªããžã§ã¯ããšäžéã®ã³ãŒã«ããã¯ãPromiseãããã³ãµãã¹ã¯ãªãã·ã§ã³ã«äŸåããŸãã å€ãã®ã³ã³ããŒãã³ãããããè¡ããšãããã«ã¡ã¢ãªã®åé¡ãçºçããŸã
makeCancellableã¯ãã³ã³ããŒãã³ããžã®åç §ãä¿æããé¢æ°ãžã®åç §ãä¿æããããšã«ãªãå¥ã®Promiseãäœæããã ãã§ãã makeCancellableãœãªã¥ãŒã·ã§ã³ã¯ãããŒã«ããããã£isMountedãpromiseã«ç§»åããã ãã§ãã
GCã®åé¡ã解決ããã«ã¯ãcancelïŒïŒãåŒã³åºãããŠãããšãã«äœããnullã«ããå¿ èŠããããŸãã ãã以å€ã®å Žåã¯ãéåæããã»ã¹ããã³ã³ããŒãã³ããžã®åç §ãã§ãŒã³ããŸã ãããŸãã
class CancellableDeferred {
constructor(request) {
this.deferred = $.Deferred();
request.then((data) => {
if (this.deferred != null) {
this.deferred.resolve(data);
}
});
request.fail((data) => {
if (this.deferred != null) {
this.deferred.reject(data);
}
});
}
cancel() {
this.deferred = null;
}
promise() {
return this.deferred.promise();
}
}
->ã¯ãjQueryã®é 延ãªããžã§ã¯ãã§ãããè¡ãæ¹æ³ã§ãã ç§ã¯PromiseAPIã«ããŸã詳ãããªãã®ã§ãã©ã®ããã«è¡šç€ºããããããããŸããã ãŸããcancelïŒïŒãåŒã³åºãããé 延ã解決ãããŠããªãå Žåãããã¯é 延ãæåŠããŸããã ããããããããã©ã®ããã«æ©èœãããã«ã€ããŠã人ã ã¯ç°ãªãæèŠãæã£ãŠããŸãã
ãããã£ãŠããã§ãŒã³ã¯æ¬¡ã®ããã«ãªããŸãã
AJAXãªã¯ãšã¹ã->ã¯ããŒãžã£-> CancellableDeferredInstance-> JQuery Deferred-> Component
ãã£ã³ã»ã«åŸã¯æ¬¡ã®ããã«ãªããŸãã
AJAXãªã¯ãšã¹ã->ã¯ããŒãžã£-> CancellableDeferredInstance /ãªããžã§ã¯ãåç §ãnullã«ãªããŸãã/ JQuery延æ->ã³ã³ããŒãã³ã
ãã®ãããAJAXãªã¯ãšã¹ãã¯ãã³ã³ããŒãã³ããGCdã«ãªãã®ã劚ããªããªããŸãã[延æãžã®åç §ã誀ã£ãŠä¿æããããšã«ãã£ãŠãã©ããã§å®è£ ãå°ç¡ãã«ããŠããªããšä»®å®ããŸãã ã€ã§ãŒã€ã¯ããŒãžã£ãŒ....]
ããã«ã¡ã¯@benmmurphy ãç§ã¯JSã¬ããŒãžã³ã³ãã€ã«ã«ããŸã粟éããŠããããReactã§ã¯åäœãç°ãªãå¯èœæ§ããããŸãããç解ã¯ç°ãªããŸãã
makeCancellable
䜿çšãããšãReactã³ã³ããŒãã³ããããŠã³ã解é€æã«ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã§ããŸãã 説æããŸãã
makeCancellableã¯ãã³ã³ããŒãã³ããžã®åç §ãä¿æããé¢æ°ãžã®åç §ãä¿æããããšã«ãªãå¥ã®Promiseãäœæããã ãã§ãã makeCancellableãœãªã¥ãŒã·ã§ã³ã¯ãããŒã«ããããã£isMountedãpromiseã«ç§»åããã ãã§ãã
makeCancellable
ïŒ
handleError() {
if (this.isMounted()) {
console.log('ERROR')
}
}
makeCancellable
ïŒ
promise.then(...).fail((reason) => {
if (reason.isCancelled) return;
console.log('ERROR');
})
makeCancellable
ããªããŠãã this
ãžã®åç
§ããããããã³ã³ããŒãã³ããããŠã³ã解é€ããããšãã«ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãè¡ãããšã¯ã§ããŸããã ãã ããä»ã®ã±ãŒã¹ã§ã¯ãã³ã³ããŒãã³ããããŠã³ã解é€ããããšããã«ãã£ã³ã»ã«å¯èœãªPromiseã®å€±æãã³ãã©ãŒãåŒã³åºããããããåç
§ãã¶ãäžããããšã¯ãããŸããã
@vpontis
åé¡ã説æããnodejsã³ãŒããããã€ããããŸãã Fooã³ã³ããŒãã³ãã¯ãéåæã³ãŒã«ããã¯resolve
ãnullã«èšå®ãããå Žåã«ã®ã¿GCãããŸãã ããšãã°ã解決ã«30ç§ãããajaxãªã¯ãšã¹ããå®è¡ããŠãããã³ã³ããŒãã³ããã¢ã³ããŠã³ãããããšããŸãã ãã®åŸãã³ã³ããŒãã³ãã¯30ç§éGCdãããŸããã ããã¯ãisMountïŒïŒã®å»æ¢ã§è§£æ±ºããããšããŠããåé¡ã®1ã€ã§ãã
npm install promise
npm install weak
node --expose-gc gc.js
first gc Foo {}
after first gc Foo {}
after resolve = null Foo {}
foo gc'd
after second gc {}
https://gist.github.com/benmmurphy/aaf35a44a6e8a1fbae1764ebed9917b6
ç·šéïŒ
ããªãã®åã§è©±ããŠãã¿ãŸããããåããŠæçš¿ãèªãã ãšããããªããäœãããããšããŠããã®ãç解ã§ããŸããã§ããããä»ã¯ç解ããŠãããšæããŸãã ãšã©ãŒã³ãŒã«ããã¯ã«ã³ã³ããŒãã³ããžã®åç §ãå«ãŸããŠããªãïŒãŸãã¯ã³ã³ããŒãã³ããžã®åç §ã«åŸããªãïŒãããã³ã³ããŒãã³ãã¯Promiseã«ãã£ãŠåç §ãããŠãããšã¯èŠãªãããªããšããããšã§ãã ããã¯å®éã«ã¯çå®ã§ãã ããŠãæåã®éšåã¯æ¬åœã§ãã ãã ãããã®æšè«ã«ã¯åé¡ããããŸãã
1ïŒäŸã®ãšã©ãŒãã³ãã©ãŒã«ã¯ã³ã³ããŒãã³ããžã®åç
§ããããŸããããéåžžã¯then()
ã³ãŒã«ããã¯ã«ãããŸãã ããšãã°ã then
ãã³ãã«ã¯éåžžthis.setState(...)
ãŸãã
2ïŒäŸã®ãšã©ãŒãã³ãã©ãŒã«ã¯ã³ã³ããŒãã³ããžã®åç
§ããããŸããããã»ãšãã©ã®ãšã©ãŒãã³ãã©ãŒã«ã¯åç
§ããããŸãã ããšãã°ã次ã®ãããªããšãããŸãã
promise.then(...).fail((reason) => {
if (reason.isCancelled) return;
console.log('ERROR');
this.setState({error: true});
})
3ïŒã³ãŒããthen()
ã³ãŒã«ããã¯ã«åŸããã isCancelled
å€æ°ããã§ãã¯ããåŸãGCããããèªèããªããšãé¢æ°ãçµäºããããšãããã£ãŠããŠãã
ãããŠã誰ããç§ã®äŸãŸãã¯ããã«åºã¥ãäœãã䜿çšããåã«ããããå®éã«æ£ããGCãããŠããããšããã¹ãããããšã確èªããŠãã ããã ç§ã¯ãŸã ç§ã®ãã¹ããããŠããŸããããããŠç§ãããã€ãã®ã°ããããšã©ãŒãããã®ã§ãããããŸããããªããŠãç§ãé©ãããŸããïŒ/
promise APIã®èŠ³ç¹ããã¯ãããã¯ãGCã®èŠ³ç¹ããnodejsã§æ©èœããŸãã ãã ããã¯ããŒãžã£ã®è¿ãã«_resolve
ã _reject
ãã©ã¡ãŒã¿ãé
眮ããããªãã®ã¯ããããJSä»æ§ã«åŸã£ãŠæ©èœããããšãä¿èšŒãããŠãããã©ããããŸãã¯ããŸããŸæ©èœãããã©ãããããããªãããã§ããããŒããããã€ãã®æé©åãè¡ã£ãŠããããã§ãã å®è£
ã¯ã衚瀺ãããŠãããã¹ãŠã®å€æ°ããã£ããã£ã§ããŸããããããšãã¯ããŒãžã£ãŒã§åç
§ãããŠããå€æ°ã ãããã£ããã£ã§ããŸããïŒ JSãå®éã«ç解ããŠãã人ããã£ã€ã ã鳎ãããŠèª¬æã§ãããããããŸãã:)
var makeCancelable = (promise) => {
let resolve;
let reject;
const wrappedPromise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
promise.then((val) => {
if (resolve != null) resolve(val)
});
promise.catch((error) => {
if (reject != null) reject(error)
});
});
return {
promise: wrappedPromise,
cancel() {
resolve = null;
reject = null;
},
};
};
isMountedé¢æ°ã¯16.0ã§åé€ãããŸããïŒ
@istarkovã³ãŒãã«ããå°ããªæ¹åã®ææ¡ïŒ
const makeCancelable = (promise) => {
let hasCanceled_ = false
promise.then((val) =>
hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
)
.catch((error) =>
hasCanceled_ ? reject({isCanceled: true}) : reject(error)
)
return {
promise,
cancel() {
hasCanceled_ = true
}
}
}
æ°ããçŽæãåé·ã§ãããšããã ãã§ãã
æ°ããçŽæãåé·ã§ãããšããã ãã§ãã
@BnayaZil resolve
ããã³reject
é¢æ°ãåŒã³åºããŠããŸãããããããã©ãããæ¥ãã®ãã¯äžæã§ãã Promise.resolve
ãšPromise.reject
ã§ããïŒ ãã®å Žåã§ããæ°ããPromiseãè¿ãããšã«ãªããŸãã
æ°æ¥åã«ãfetchïŒïŒãªã¯ãšã¹ããäžæ¢ã§ããæ°ããAPIãDOMä»æ§ã«è¿œå ãããŸããã ãã®APIã¯ãŸã ã©ã®ãã©ãŠã¶ã«ãå®è£ ãããŠããŸããããNPMã§å©çšã§ããããªãã£ã«ãabortcontroller-polyfillããäœæããŸããã ããªãã£ã«ã¯ã @ istarkovã«ãã£ãŠæçš¿ãããã³ãŒããšåºæ¬çã«åãããšãè¡ããŸããã
詳现ã¯ãã¡ãïŒ
https://mo.github.io/2017/07/24/abort-fetch-abortcontroller-polyfill.html
React.createClass
ã¯React 16ã«ååšããªããªããæ°ããcreate-react-class
ããã±ãŒãžã«ã¯isMounted
æ確ãªéæšå¥šã¡ãã»ãŒãžãå«ãŸããŠããããããããçµäºããŸãã
ç§ã¯@istarkovã®ãœãªã¥ãŒã·ã§ã³ãå¹æçã«äœ¿çšããã®ãšåãã§ããããšã@benmmurphyã«åæisMounted()
ããããã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã®åé¡ã解決ããŠããªãã®ã§ã
@benmmurphyã®ãœãªã¥ãŒã·ã§ã³ã¯ããè¿ãã§ãããééã£ãå€æ°ãnullã«ãããããpromiseãã³ãã©ãŒã¯éåç §ãããŸããã
éèŠãªã®ã¯ããã³ãã©ãŒãéåç §ããã¯ããŒãžã£ãŒãä»ããŠé¢æ°ãæž¡ãããšã§ãã
const makeCancelable = promise => {
let cancel = () => {};
const wrappedPromise = new Promise((resolve, reject) => {
cancel = () => {
resolve = null;
reject = null;
};
promise.then(
val => {
if (resolve) resolve(val);
},
error => {
if (reject) reject(error);
}
);
});
wrappedPromise.cancel = cancel;
return wrappedPromise;
};
ãã®ãœãªã¥ãŒã·ã§ã³ã§ä»¥åã®ãœãªã¥ãŒã·ã§ã³ã§ã¯ãªãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãå¯èœã«ãªãçç±ã«ã€ããŠã®è©³çŽ°ã¯ããã¡ããã芧ãã ããã
ç§ã¯å ã«é²ã¿ããããnpmããã±ãŒãžã«å€æããŸããã ãããŠããŠãŒã¹ã±ãŒã¹ã¯reactã§ããããã promiseã远跡ããã³ã³ããŒãã³ããããŠã³ã解é€ããããšãã«ãããããã£ã³ã»ã«ããHOCã³ã³ããŒãã³ããäœæããŸããã
ç·šéïŒç§ã®æªããç§ã¯ã¡ããã©@hjylewis thrashableãèŠãŸããããããŠããã¯åæ§ã«çŽæããã£ã³ã»ã«ããŸãã ããã§ãã以äžã®ãã¿ãŒã³ã¯IMOã®å°ããªæ¹åã§ãã
ãããã®ãœãªã¥ãŒã·ã§ã³ã¯ãããããçŽæããã£ã³ã»ã«ããŸãããçŽæã¯ãæ°žé ã«ä¿çäžã®çŽæãåžåããããšã«ããã延é·
function makeCancelable(promise) {
let active = true;
return {
cancel() {active = false},
promise: promise.then(
value => active ? value : new Promise(()=>{}),
reason => active ? reason : new Promise(()=>{})
)
}
}
// used as above:
const {promise, cancel} = makeCancelable(Promise.resolve("Hey!"))
promise.then((v) => console.log(v)) // never logs
cancel()
GCã«é¢ããŠã¯åŸ®åŠãªåé¡ããããããããŸããããã³ãŒããŒã¯ãŸã éå§ãããŠããŸãããããã®ãã¿ãŒã³ã«ãããè¿ãããçŽæãå®éã«ãã£ã³ã»ã«ããããªãŒã¯ããªãããã«ããããšãã§ããŸãïŒéå»ã«å®è£ ããŸããïŒã
@pygyè¿ä¿¡ããããšãããããŸãïŒ
æ®å¿µãªãããããªãã®ãœãªã¥ãŒã·ã§ã³ã¯ãŸã ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãèš±å¯ããŠããŸããã åºæ¬çã«ãæ¡ä»¶ä»ãã䜿çšãã@istarkovã®ãœãªã¥ãŒã·ã§ã³ãæžãçŽããŸããã
ãã®å®è£ ããã¿ç®±ã«å ¥ããŠãã¹ããå®è¡ããããšã§ããããç°¡åã«ãã¹ãã§ããŸãïŒã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãã¹ãã¯å€±æããŸãïŒã
ãŸããå®è£ ã¯ãšã©ãŒãé©åã«åŠçã§ããŸããã
2018幎ã§ãããäžèšã®ã¢ãããŒããããããã«åªããã¢ãããŒãã¯ãããŸããïŒ
ã¯ããReact Nativeã®2åã®ãµã€ãºã®ããã¥ã¡ã³ãããããŸãããéåžžã«å°éçãªããã²ãŒã·ã§ã³ãã¬ãŒã ã¯ãŒã¯ã䜿çšã§ããŸãã
çŽæãããã£ã³ã»ã«ãããããã®ãããã®ã¹ããããã¯ãããã»ã©çŽ æŽãããç§èŠã§ã¯ãããŸããã ãã£ã³ã»ã«ããããããã¹ã¯ãå ã®ãããã¹ã解決ãããŸã§è§£æ±ºãããŸããã ãããã£ãŠãã¡ã¢ãªã®ã¯ãªãŒã³ã¢ããã¯ãisMountedããªãã¯ã䜿çšããå Žåã«çºçãããŸã§çºçããŸããã
é©åãªãã£ã³ã»ã«å¯èœãªpromiseã©ãããŒã¯ã2çªç®ã®promiseãšPromise.raceã䜿çšããå¿
èŠããããŸãã ã€ãŸãã Promise.race([originalPromise, cancelationPromise])
@benmmurphyã®ãœãªã¥ãŒã·ã§ã³ã¯ããè¿ãã§ãããééã£ãå€æ°ãnullã«ãããããpromiseãã³ãã©ãŒã¯éåç §ãããŸããã
ç§ã®ãœãªã¥ãŒã·ã§ã³ã¯æ©èœãããšæããŸãããjavascriptã©ã³ã¿ã€ã ã確å®ã«ç¥ãããšãçŽæãããã®ã«ã€ããŠã¯ååã«ããããŸããã ãã¹ãããŒãã¹ã®ããŒãã®äžã§ãœãªã¥ãŒã·ã§ã³ãå®è¡ãããšãå€ãæ£ããGCãããŸãã ç§ã®ãœãªã¥ãŒã·ã§ã³ã§ã¯ã解決/æåŠé¢æ°ãããé«ãã¹ã³ãŒãã«å²ãåœãŠãcancelãåŒã³åºããããšãã«ãããã®å€ãç¡å¹ã«ããŸããã ãã ããé¢æ°ã¯åŒãç¶ãäžäœã¹ã³ãŒãã§äœ¿çšå¯èœã§ããããåç §ãããŠããŸããã§ããã æè¿ã®JavaScriptãšã³ãžã³ã¯ãåç §ãããŠããªãéããã¯ããŒãžã£å ã®å€æ°ããã£ããã£ããªããšæããŸãã ããã¯ã人ã ã次ã®ãããªããšãããããã«èª€ã£ãŠDOMãªãŒã¯ãäœæãããšãã倧ããªåé¡ã ã£ããšæããŸããvarelement= findDOMïŒïŒ; element.addEventListenerïŒ 'click'ãfunctionïŒïŒ{}ïŒ; ã¯ããŒãžã£ãŒã§äœ¿çšãããŠããªããŠããèŠçŽ ã¯ã¯ããŒãžã£ãŒã§åç §ãããŸãã
@hjylewis @benmmurphyãªããã³ãã©ãŒãéåç §ããå¿ èŠãããã®ã§ããïŒ ãã³ãã©ãŒãå®è¡ãããåŸãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã¯ã©ãã«ãèµ·ãããŸããã??
çŽæãããã£ã³ã»ã«ãããããã®ãããã®ã¹ããããã¯ãããã»ã©çŽ æŽãããç§èŠã§ã¯ãããŸããã ãã£ã³ã»ã«ããããããã¹ã¯ãå ã®ãããã¹ã解決ãããŸã§è§£æ±ºãããŸããã ãããã£ãŠãã¡ã¢ãªã®ã¯ãªãŒã³ã¢ããã¯ãisMountedããªãã¯ã䜿çšããå Žåã«çºçãããŸã§çºçããŸããã
é©åãªãã£ã³ã»ã«å¯èœãªpromiseã©ãããŒã¯ã2çªç®ã®promiseãšPromise.raceã䜿çšããå¿ èŠããããŸãã ã€ãŸãã
Promise.race([originalPromise, cancelationPromise])
@hjylewisãšç§ã®ãã®ã¯å®éã«åäœããŸããïŒããŒãweakã§æ€èšŒã§ããŸãã ããããããããããäžåºŠèŠããšãã©ã¡ããç¹ç°ãªæžé¢ã«ããçŽæã³ãŒãã§ã¯ãªãããšã«åæããŸãã promiseãŠãŒã¶ãŒãšããŠãããã£ã³ã»ã«ããããpromiseãæåŠãããç¶æ ã§è§£æ±ºãããããšãæåŸ ããå¯èœæ§ããããŸãããã©ã¡ãããããè¡ããŸããã ãã ããã³ã³ããŒãã³ãã®å Žåãããã¯ãæåŠãã³ãã©ãŒãç¡èŠããããã«äœåãªã³ãŒããèšè¿°ããå¿ èŠããªãããããã䜿ãããããœãªã¥ãŒã·ã§ã³ã§ãã
ç¹ç°äœè³ªã®æåŠå¯èœãªpromiseã¯ãPromise.raceïŒ[]ïŒã䜿çšããŠãã£ã³ã»ã«å¯èœãªpromiseãæ§ç¯ãããšæããŸãã ããã¯ãPromiseã解決ããããšä¿çäžã®ã³ãŒã«ããã¯ãåé€ãããããããã®æç¹ã§ãã¬ãŒã¹Promiseãšã³ã³ããŒãã³ãã®éã«åç §ããªããªãããããã©ãŠã¶ãŒãããã¯ãŒã¯ããã³ã³ããŒãã³ããžã®åç §ãã§ãŒã³ããªããªãããã«æ©èœããŸãã
ãããã®ãã£ã³ã»ã«å¯èœãªpromiseã§Promise.all()
ã䜿çšããŠããã©ãŠã¶ã³ã³ãœãŒã«ã§ãã£ãããããªããšã©ãŒãåé¿ã§ãããã©ããç¥ãããã§ã...æåã®ãã£ã³ã»ã«ãšã©ãŒãããã£ããã§ããªããããä»ã®ãšã©ãŒã¯ãã£ãããããªããŸãŸã§ãã
2018幎ã§ãããäžèšã®ã¢ãããŒããããããã«åªããã¢ãããŒãã¯ãããŸããïŒ
çŽæã®å®è¡ããã£ã³ã»ã«ããããã®ããè¯ãã¢ãããŒããã€ãŸãsetTimeoutãAPIåŒã³åºããªã©ã2019幎ã§ãðð
TC39ã§é²è¡äžã®Promiseãã£ã³ã»ã«ã¹ã¬ããããããŸããïŒç§ã¯æãïŒããã¯ããã§é¢é£æ§ããããŸãïŒå€å..ããããªãïŒ
https://github.com/tc39/proposal-cancellation/issues/24
çŽæã®å®è¡ããã£ã³ã»ã«ããããã®ããè¯ãã¢ãããŒããã€ãŸãsetTimeoutãAPIåŒã³åºããªã©ã2019幎ã§ãðð
ç§ãã¡ã¯æ¬¡ã®ãããªãã®ãæ¢ããŠããŸãã
const promise = new Promise(r => setTimeout(r, 1000))
.then(() => console.log('resolved'))
.catch(()=> console.log('error'))
.canceled(() => console.log('canceled'));
// Cancel promise
promise.cancel();
æãåèã«ãªãã³ã¡ã³ã
ãã®ç°¡åãªæ¹æ³ã䜿çšããŠãä»»æã®çŽæã«ãã£ã³ã»ã«ãè¿œå ã§ããŸã
ç·šéïŒæ£ç¢ºæ§/å®å šæ§ã®ããã«æŽæ°ãããŸããã
䜿ãæ¹