ç§ã¯äžæ žä»¥å€ã®æè²ãš10幎以äžã®çµéšãæã€Webéçºè ã§ãã ç§ã¯é¡§å®¢ã®ããã«ãæã«ã¯äžåžã«ããèµ·ãããªããŠã§ãã®ããã«ãã¹ãŠãããŸããã ãã®ä»äºã倧奜ãã§ãã ããããããã§ãç§ã¯ãŸã£ããç¬ããã«ããããšãããã€ããããŸãã ãããã®1ã€ã¯ãã¡ã€ã«ã¢ããããŒããŒã§ãã æåãã-ããã誰ã«ãèµ·ãããã«ajaxã«ãªã£ããšã-ãããŠä»ãŸã§-ããã¯åçã®ãµã€ãºãå€æŽããããã€ãã®ã¹ããªãŒã ã«ãã¡ã€ã«ãã¢ããããŒãããã¯ããã«-ããã¯ç§ã«ãšã£ãŠæãæãããŠããªãã¿ã¹ã¯ã®1ã€ã®ãŸãŸã§ã ãªããšãåŠçã§ããããã§ãã èå³ãããã°ãç«ãžããããã
ã¡ãã£ãšããCoffeescriptãjQueryã«é¢ããããªãã®äžæºã$ .Deferredã®ç°¡åãªèª¬æãã€ã³ãã¬ãŒã¹ãšã¢ãŠããªããã¬ãŒã¹ã®äžæ³šæã«é©çšããããã¿ãŒã³ããããŠé¢çœãé¢çœãæ¬ãžã®ãªã³ã¯ãããªããåŸ ã£ãŠããŸãã
ãããã£ãŠãç§ãã¡ã®åã®ã¿ã¹ã¯ã¯ããã¡ã€ã«ã¢ããããŒããŒããµã€ãã«ã¢ããããŒãããããšã§ãã ãã¡ãããAJAXã¯ãã¡ãããé²è¡äžã§ãããã¡ãããæ¢ã«å®æãããã¶ã€ã³ã§ãã ãããã-ãªããããåé¡ãªã®ã§ããïŒ ã¯ãã¹ãã©ãŠã¶ã å€ãè¯ãããªãã¯ïŒi-frameã§ã®a-laéä¿¡ãã©ãŒã ïŒã¯é²æ©ãããããããæ°ãããã®ïŒxhr.sendïŒã¯å€ããã©ãŠã¶ã§ã¯æ©èœããŸããã ãã©ãŠã¶ã®æšæºåã çªç¶åæ¢ããã¯ãã¹ãã©ãŠã¶ã®åé¡ãæ»ãªãªãããã«ãšããåžæããããŸããã è¿œå ã®ã¿ã¹ã¯ã¯ããã©ãã°ã¢ã³ãããããã§ãã input'aã®å€èŠ³ã«ã¯ãŸã åé¡ããããŸãã
ã©ã®ãããªãªãã·ã§ã³ããããŸããïŒ
æ¹æ³No. 1ãGoogleäž»å°ã®éçº
Shustrenkoã¯ãå¿ èŠãªãã¹ãŠã®æ©èœãå®è£ ããããªã人æ°ã®ããjQueryã©ã€ãã©ãªãŒãgoogleããŸãã ã¢ãããŒãã¯æéã®äžè¶³ã§æ£ããã§ãã ãããžã§ã¯ãã«éåžžã«è¿ éã«çµ±åããããã©ãŠã¶ãšã®äºææ§ãå¿é ãããã©ãŒããããããDOMã衚瀺ããŸãã çµå±ã®ãšãããDOMãã¹ã¿ã€ã«ã§åå å·¥ããŠãåé¡ã¯ãããŸããïŒjQueryã䜿çšããŠãããããäž»ãªå°éåéã§ãããïŒãæ©èœã«ã€ããŠèå³ã®ããé¢ä¿è ïŒãã¯ããããã§ã¯ãããŸãããããããå¶çºçã«çºçãããããã®çš®é¡ãèŠãŠãã ãããæ¬åœã«ãããã§ããïŒãïŒã ãããŠããã¹ãŠãã¹ãŒããŒã§ããããã«èŠãããã¹ãŠãçŽ æŽãããããã§ãã 1æ¥éããããåŠçããŠãã¹ãã«æž¡ãããšã¯ããªãå¯èœã§ãã ãããããã®åŸ...æåã®ããã¡ã¯ãã¶ã€ããŒããé£ã³åºããŸã-ããã€ãã®æ姫ãåºãŸããïŒèª°ããããŠã³ããŒããäžæããããå¥ã®ãããšããŸããã¯ãªç¶æ³ãäœãåºããŸããïŒ ãããããã®divã¯è¡šç€ºãããªãã£ããããæ§ããã«èšã£ãŠãããã®divã®ã¹ã¿ã€ã«ã¯ãŸã£ããåãã§ã¯ãããŸããã ãã¶ã€ããŒã®åœç¶ã®éé£ãæ¶åãããã¹ã¿ãŒã®ä»£è¡šå£ã®å°çã芳å¯ããŸãã äŒæ¥ã®æšæºã«ããããŠãŒã¶ãŒã®XXããŒã»ã³ãïŒããã³æã䟡å€ã®ãããŠãŒã¶ãŒïŒãåããŠããçŽ æŽããããã©ãŠã¶ãŒã§ã¯ãé²è¡ç¶æ³ã衚瀺ãããŸããã ãã©ãŒ ãã¹ã¿ãŒãå°çã«éã£ãŠãã ããïŒããã©ãŠã¶ããµããŒãããŠããªãå Žåãã©ãããã°ããã§ããïŒãïŒãåå©ã®è¡šæ ã§ãããã®ããã¯ãã¹ãããããŸãïŒãVkontakteã¢ããããŒãã¯ãã®ãã©ãŠã¶ã§åäœããŸãïŒã ãããŠãã®ç¬éããããžã§ã¯ãã«å¯ŸããŠææªã®ç¯çœªã®1ã€ãç¯ããŸãããã®çŽ æŽããããã©ã°ã€ã³ã®ãœãŒã¹ã³ãŒãã«ã¢ã¯ã»ã¹ããŸãã ïŒãªãã·ã§ã³ãšããŠãæšå¹Žããåã«ãã©ã°ã€ã³ãã©ãã«ãŒã§ãã®ãšã©ãŒã«é¢ããã¡ãã»ãŒãžãèŠã€ããéãè¯ããã°ããã®ç¹å®ã®åé¡ããã©ã°ã€ã³ããäœããã®æŸèæãèŠã€ããŠãã ããïŒã å®éãããã¯ããã°ã©ããŒã»ã©æããªãã ããªãã¯èª°ãã®ã³ãŒããèªãããšãåŠã¶ã§ããã-æã«ã¯è¯ããæã«ã¯...ç°ãªãã ãããã¬ãŒãããäžåºŠäœ¿çšããŸãã jQueryã®ãã©ã°ã€ã³éçºè ã«ã€ããŠæªãããšãèšãããã¯ãããŸããã ç§ãåºäŒã£ãã»ãšãã©ã®å Žåã圌ãã®ã³ãŒãã¯éšå€è ããµããŒãããããã«èšèšãããŠããªãã ãã§ãã ãããããããžã§ã¯ãã®ã¿ã€ãã³ã°ãçãå§ããå¯èœæ§ããããŸãã æéããªãããããã®ãªãã·ã§ã³ãéžæããããšãèŠããŠããŸããïŒ
ããã§ãããŸã ãã©ã°ã€ã³ããã©ã°ã€ã³ããŠããå Žåã¯ããããžã§ã¯ããªããžããªã«ãã©ã°ã€ã³ã®çž®å°ããŒãžã§ã³ã®ã¿ãæ®ããŠãã ããã ãŸãããã©ã°ã€ã³ãµã€ããžã®ãªã³ã¯ãã©ãã«ãæ®ããªãã§ãã ããã
èŠçŽïŒãã¶ã€ã³ãšæ©èœãè£ãããšãã§ããå Žåã«ã®ã¿ã銎æã¿ã®ãªããã©ã°ã€ã³ã䜿çšããŸãã ãŸãããŸãã¯ãã¶ã€ããŒãä»ã®ãã¹ã¿ãŒã®åŸ©//ãã¬ãŒãã³ã°ã®ããã«ã ãŸãã¯ããªããŒã¹ãšã³ãžãã¢ãªã³ã°ã¹ãã«ã®ãã¬ãŒãã³ã°ãšããŠã
ãã¹çªå·2ãå±¥æŽ
ãïŒ å幎åãç§ãã¡ã¯ãã§ã«ãã®ãããªãã®ãæžããŸããã ãªã©ã³ã人ïŒã®ãªã·ã£äººããªãŒã¹ãã©ãªã¢äººããã«ã·ã£äºº...ïŒ ç·è²ã®æ¥å圢ã®é²è¡ç¶æ³ããŒããŸã ãããŸããã å€ããããžã§ã¯ããéããŸãïŒå¥ã®ã³ã³ãã¥ãŒã¿ãŒãçãå°œãããªããžããªãŒãããã³ããã»ã©åçŽã§ã¯ãªãå¥ã®100500ã®çç±ïŒã ã¢ããããŒããŒãèŠããç ã®çš®é¡ã ãããŠãã...æåã«-ææ°ã®ãã©ãŠã¶ã®ã¿ã®ãµããŒãã 次ã«ãã¯ã©ã€ã¢ã³ãåŽã®ãã©ãã·ã¥ã®ãµã€ãºå€æŽã 第äžã«ããã®æãèšæ¶ã«æ®ãæ¥å圢ïŒãã¶ã€ããŒã¯ã¹ã«ã ã§ãïŒïŒé²è¡ç¶æ³ã¯ã¢ããããŒããŒã³ãŒãèªäœã«çµã¿èŸŒãŸããŠããŸãã 4çªç®ã5çªç®ãªã© ããã«ããã®ç¹å®ã®ãããžã§ã¯ãã®è©³çŽ°ã®æã åã³ã®èŠ³ç¹ãã-ãŸããæ°·ã§ã¯ãããŸããã å幎ã®ããŒã«ããã¯-çŸä»£ã®æè¡ã®å±±ã®é«ãã«æèãé£ã°ãã®ã§ã¯ãªãã
èŠçŽïŒé¢çœããªãã 6ãæåã«ç¬¬äžäººè ã§ãããé«å質ã®ã³ãŒãã®ã¿ãæäŸãããšããŠãããšã«ããã¯ãŒã«ã«ãªããŸããã
ãã¹çªå·3ãäºæ³å€ã®
ããã§ã¯ãå°ã倢ãèŠãŠã¿ãŸãããã äœã欲ããïŒ ïŒããŒã«ãé£äººãç«ã«å ããŠïŒã å°ãªããšã-ã¢ããããŒããŒãäœãããã§ãã æ倧éãäžåºŠã ãé·ãéãããããšæã£ãŠããŸãã çŸåšã®ãããžã§ã¯ãããç°¡åã«åãåºããŠãæå°éã®å€æŽã§æ¬¡ã®ãããžã§ã¯ãã«è²Œãä»ããããšãã§ããŸãã ã¡ãªã¿ã«ããã®æ¬²æ±ã¯ãEricãšElizabeth Freimenovã«ãããDesign Patternsããšãã1ã€ã®é¢çœãå°ããªæ¬ã«è§ŠçºãããŠããŸãã ããããããã¯èª°ããèªãã¹ã4人çµã®ãªãªãžãã«ã®æ¬ã§ã¯ãããŸããã ãã®ãã1ã€ã®æ¹ãã¯ããã«ç°¡åã§ãã ããã»ã©åŒ·ããªãããèªã¿ãããã èè ãèªè ã®é ã«è¿œã蟌ãããšããæåã®ååã®1ã€ã¯ãå€åããŠãããã®ãã«ãã»ã«åããããšã§ãã ç§ãã¡ã®å Žåãã¢ãŒããã¯ãã£ã®æãå¯å€çãªåŽé¢ã¯ããµãŒããŒã«ããŒã¿ãéä¿¡ããæ¹æ³ã§ããå¿ èŠããããŸãïŒããã ãã§ãªããåŸã§è©³ãã説æããŸãïŒã èŠããŠãããªããjQueryãã©ã°ã€ã³ã®åã«ãã®åé¡ã«ã€ããŠè°è«ããŸããã ãããã£ãŠããµãŒããŒã«ããŒã¿ãéä¿¡ããããã®ã¡ã«ããºã ã®ããŒã«ãäœæãïŒããå€ãã®OOPã®å®åŒåãå¿ èŠãªå Žå-å ±éã®ã€ã³ã¿ãŒãã§ã€ã¹ãæã€ã¯ã©ã¹ã®ã»ããããããŸãïŒãã¢ããããŒããŒãšã®å¯Ÿè©±ã€ã³ã¿ãŒãã§ã€ã¹ãå®çŸ©ãããš-1ã€ã®å€§ããªåé¡ã¯ããã€ãã®å°ããªåé¡ã«åå²ãããŸãã ãããŠããããã解決ããããšã¯ãã§ã«ããè¯ãã§ãã ã©ã®ããã«èŠããŸããïŒ éåžžã«ã·ã³ãã«ïŒ
Uploader = senders: [xhrFile, formDataFile, formDataForm, iframe] send: (options)-> stream = false $.each @senders, (i, func)=> if stream = func(options) false stream
2èªã§-é¢æ°ã®é åã䞊ã¹æ¿ãïŒjavascriptãåãã§ãïŒïŒãåé¢æ°ã«ã¯ãªãã·ã§ã³ããããŸãïŒå®éã«è§Šèšºããå 容ãåãããªãããã倧éšåã¯ïŒãæåã«è¿ããã空ã§ãªãçµæãéä¿¡ã«äœ¿çšãããŸãã ïŒãªãã·ã§ã³ãšããŠãäŸå€ãã¹ããŒããªãã£ãæåã®ãã®ãããæ£ç¢ºã§ããããããŸã§ã®ãšããæ zyã§ããïŒãã®å Žåãæãã䟡å€ã®ãããé¢æ°ã¯é åã®æåã§ãããæåŸã¯ãã§ã€ã«ã»ãŒãã§ãïŒåãsubmit-form-to-iframeã¡ãœããïŒã ã¯ããdeferredãé¢æ°ãè¿ããšæ¢ã«æšæž¬ããŠããŸã-ãããŠãã¢ããããŒããŒã€ã³ã¿ãŒãã§ãŒã¹ã§ãé¢å¿ã®ãããã¹ãŠã®ãªã¹ããŒããã³ã°ã¢ããããŸãïŒãããŠããããããªãã·ã§ã³ã«æž¡ããŸããïŒã 圌ã¯ãé¢æ°ã®äŸã®åŸããã¿ãã¬ã®äžã§å°ãæ··ä¹±ããŠããããšã説æããŸããã
ããã§ããã®èšäºã®ã³ãŒãã®å質ã«é¢ããæ°è¡ïŒ
-ã³ãŒããjQueryã«é¢é£ä»ããããŠããã®ã¯ãäœè ããããžã§ã¯ããé ããæ©ããããã䜿çšãããšèããŠããããã§ã¯ãªããDeferredãå«ãäžå®æ°ã®ãã¢ã¡ããã£ãã®ããã§ãã
-éšåçã«ã³ãŒãã¯1ã€ã®çŽ æŽããããã©ã°ã€ã³ããåãããŸã ã æ£çŽã«èšããšããã®ãã©ã°ã€ã³ãšãããæ³£ããèªãããšããã¢ã€ãã¢ãçãŸããŸãããããŸãããªãããªãããžãã¯ãå®è£ ããåé¢ãããªãã®ã§ããïŒã
-çŸæç¹ã§ã¯ãã³ãŒãã®ãã¹ãã¯ããªãäžååã§ãããããã¯ã¢ãŒããã¯ãã£ã®åãªãäŸç€ºã§ãã
é¢æ°ã®äŸïŒ
iframe = (options)-> return false unless options.input && options.input.value id = 'frame' + Math.random() $form = $ '<form>', method: options.method, enctype:'multipart/form-data', target: id, action: options.url $('<iframe>', name: id ).appendTo($form).on 'load', -> try response = @contents() throw new Error unless response.length && response[0].firstChild dfd.resolve response, name: options.input.value catch e dfd.reject response, name: options.input.value $form.hide().appendTo('body').submit() (dfd = $.Deferred()).promise()
ããã¯ãå€ããã©ãŠã¶ãŒã®å Žåãšåãã¢ããã¿ã€ã æ©èœã§ãã èŠããã«ããã©ãŒã ãäœæããiframeãç®æããŠãéä¿¡ããŸãã é 延ãè¿ããŸããããã¯ãã¿ãŒã²ããiframeãããŒãããããšã§è§£æ±ºãŸãã¯ãªãã€ã¬ã¯ããããŸãã deferredã«æž¡ãããåŒæ°ã¯ãå€éšãªã¹ããŒã§åä¿¡ãããŸãã 延æã®èª¬æãå®å šã«æ確ã§ãªãå Žåã次ã®æ©èœã®åŸã«ã¹ãã€ã©ãŒãæè¿ããŸããããã¡ããã ãããããã¥ã¡ã³ãã® æçš¿ãªã©ãèªãããšããå§ãããŸã ã
formDataFile = (options)-> return false unless options.files && options.files.length && window.FormData $.when.apply $, options.files.map (f)-> formData = new FormData() formData.append options.name, f xhr = new XMLHttpRequest() dfd = $.Deferred() xhr.onload = xhr.onerror = ->dfd[@status == 200 && 'resolve' || 'reject'] @response, file if xhr.upload xhr.upload.onprogress = (e)->dfd.notify e, file xhr.open options.method, options.url, true xhr.responseType = 'text' xhr.send formData dfd.promise()
ãã§ã«ãã£ãšé¢çœããã®ãããã§ãããã æå®ãããåãã¡ã€ã«ïŒoptions.filesãã©ãããæ¥ãŠããã®äžã«äœããããïŒããšã«ãåå¥ã®XMLHttpRequestãäœæããé 延ããŸãã æåã®äŸã®ããã«ããµãŒããŒããããŒã¿ãããŒãããããã«ãªãã€ã¬ã¯ããŸãã¯è§£æ±ºããŸãã ãã§ã€ã«ã»ãŒãã®æ¹æ³ãšã¯å¯Ÿç §çã«ã解決/æåŠã«å ããŠããã©ãŠã¶ãæ¯é ããå Žåãã¢ããããŒãã®é²è¡ç¶æ³ã«é¢ããé 延ããŒã¿ïŒxhr.upload.onprogress =ïŒeïŒ-> dfd.notify eãfileïŒãéä¿¡ããŸãã deferredã䜿çšããŠã$ .whenã䜿çšããŠãããã1ã€ã«ã°ã«ãŒãåããŠæ»ããŸãã ãã®å Žåãwhenã®äœ¿çšãå®å šã«æ£åœåãããããã§ã¯ãªãã®ã§ãã³ã¡ã³ãã§ãã®çç±ãåãã§èªã¿ãŸãã
å°ããªãã®ã®ããã«å»¶æ
倧ãŸãã«èšã£ãŠãé
延ã¯ãã€ãã³ããã³ãã©ãŒã®è¿œå ããããã®ãã³ãã©ãŒã®åŒã³åºãããåé¢ããããã®ã¡ã«ããºã ã§ãã éåæåŒã³åºãã§äœ¿çšãããšéåžžã«ã¯ãŒã«ã§ãã äŸãšããŠãç§ã¯ajaxãªã¯ãšã¹ããæãé »ç¹ã«äœ¿çšãããã»ãšãã©ã®Webããã°ã©ããŒã«éŠŽæã¿ã®ãããã®ãšããŠåŒçšããŸãã 以åã¯æ¬¡ã®ããã§ããã
ä»ãã®ããã«ïŒ
äœãå€ãã£ãã®ïŒ ç§ãã¡ã«ãšã£ãŠæãéèŠãªããšã¯ãããªããèŠæ±ãå®è¡ããåã«ãããªãã¯ãã§ã«ããªããçããã©ãããããç¥ãå¿ èŠããããšããããšã§ãïŒãã³ãã©é¢æ°ã¯$ .getã®åŒã³åºãæã«æž¡ãããªããã°ãªããŸããã§ããïŒã ä»ã¯ããªãã§ãã ããã ãªã¯ãšã¹ãå€æ°ïŒé 延ãªããžã§ã¯ãã¯ãã®äžã«ä¿åãããŸãïŒãã³ãã©ãŒã§ãã³ã°ããããšãã§ããŸã
ãªã¯ãšã¹ãã®å®äºæã«ã 確ãã«ããã³ãã©ãŒã®å³æå¿çã«åããå¿ èŠããããŸãã ããã¯Deferredã®ã¯ã©ã€ã¢ã³ãïŒ "ã³ã³ã·ã¥ãŒã"ïŒåŽã§ã-$ .getã¡ãœããããé 延ãããç¶æ ãå€åããã®ãåŸ ã¡ãŸãã ãããŒã¯ããªåŽé¢ãjQueryã®ããã«æããŸãïŒ
ã¡ãœããã®è§£æ±º - 解決æžã¿ã§ãã æåã®ãã³ãã©ãŒã¯ã解決æžã¿ãç¶æ ãžã®é·ç§»ã«ãã³ãã©ãŒãè¿œå ãã2çªç®ã®ãã³ãã©ãŒã¯ãªããžã§ã¯ãããã®ç¶æ ã«ããè¿œå æžã¿ã®ãã¹ãŠã®ãã³ãã©ãŒãåŒã³åºããŸãã
倱æã®2çªç®ã®ãã¢- æåŠã¡ãœããã¯ããæåŠãç¶æ ã§ãåãããã«æ©èœããŸã
é²è¡ç¶æ³ã®3çªç®ã®ãã¢- éç¥ã¡ãœããã¯ãç¶æ ãå€æŽããã«æ©èœããŸãã éç¥ãåŒã³åºããšããã¹ãŠã®é²è¡ç¶æ³ãã³ãã©ãŒãæ©èœããã ãã§ãã
promiseïŒïŒãªã©ã®ä¿è·çãªãã®ããããŸãã ãå²ç€Œã延æãããŠããªãã«æ»ããŸãã ãã³ãã©ãŒããã³ã°ïŒå®äºã倱æãé²è¡ïŒãããããšã¯ã§ããŸãããç¶æ ãå€æŽããããšã¯ã§ããŸããã ããã$ .getãè¿ããã®ã§ãã ãããŠåœç¶ã®ããšã§ãããªããajaxãªã¯ãšã¹ãã®ç¶æ ãæåã§å€æŽããå¿ èŠãããã®ã§ããïŒ
ã³ãŒããç解ããããã«ã$ .whenãåŠçããã®ãè¯ãã§ãããã ããã¯ãé 延ãªããžã§ã¯ãã®ãçµåãã§ãã 次ã®ããã«æ©èœããŸãã
$ .whenã䜿çšããå Žåãè€åãªããžã§ã¯ãã«ãã£ãŠãã³ãã©ãŒã«æž¡ãããåŒæ°ã«æ³šæããŠãã ããã 圌ã¯ããããèç©ããŸãã ã€ãŸã é¢æ°a.resolveïŒ1ïŒããã³b.resolveïŒ2ïŒãåŒã³åºãããå Žåãè€åãªããžã§ã¯ãã®done-listenerã¯åŒæ°ãšããŠ1ã2ãåãåããŸãã ããªãã¯ãã€ãªãªã³ãæŒå¥ããããšãã§ããŸãã
ãããã ããã§ããŸãã¯å°ãªããšãããã§ãæ®ã眮ãã«ã€ããŠèªãããšããå§ãããŸã ã
$.get('/some/url/for/ajax', function(){ alert('got response'); }, function(){ alert('got error'); })
ä»ãã®ããã«ïŒ
var request = $.get('/some/url/for/ajax'); request.done(function(){ alert('got response'); }); request.fail(function(){ alert('got error'); })
äœãå€ãã£ãã®ïŒ ç§ãã¡ã«ãšã£ãŠæãéèŠãªããšã¯ãããªããèŠæ±ãå®è¡ããåã«ãããªãã¯ãã§ã«ããªããçããã©ãããããç¥ãå¿ èŠããããšããããšã§ãïŒãã³ãã©é¢æ°ã¯$ .getã®åŒã³åºãæã«æž¡ãããªããã°ãªããŸããã§ããïŒã ä»ã¯ããªãã§ãã ããã ãªã¯ãšã¹ãå€æ°ïŒé 延ãªããžã§ã¯ãã¯ãã®äžã«ä¿åãããŸãïŒãã³ãã©ãŒã§ãã³ã°ããããšãã§ããŸã
ãªã¯ãšã¹ãã®å®äºæã«ã 確ãã«ããã³ãã©ãŒã®å³æå¿çã«åããå¿ èŠããããŸãã ããã¯Deferredã®ã¯ã©ã€ã¢ã³ãïŒ "ã³ã³ã·ã¥ãŒã"ïŒåŽã§ã-$ .getã¡ãœããããé 延ãããç¶æ ãå€åããã®ãåŸ ã¡ãŸãã ãããŒã¯ããªåŽé¢ãjQueryã®ããã«æããŸãïŒ
var def = $.Deferred(); def.done(function(){ // "" ("") "" deferred- console.log('done1', arguments) }); // def.resolve('param12');// "" deferred done-, 'param12' // - ['done1', Arguments['param12']] def.done(function(){ // "" ("") "" deferred- console.log('done2', arguments) }); // // - ['done2', Arguments['param12']]
ã¡ãœããã®è§£æ±º - 解決æžã¿ã§ãã æåã®ãã³ãã©ãŒã¯ã解決æžã¿ãç¶æ ãžã®é·ç§»ã«ãã³ãã©ãŒãè¿œå ãã2çªç®ã®ãã³ãã©ãŒã¯ãªããžã§ã¯ãããã®ç¶æ ã«ããè¿œå æžã¿ã®ãã¹ãŠã®ãã³ãã©ãŒãåŒã³åºããŸãã
倱æã®2çªç®ã®ãã¢- æåŠã¡ãœããã¯ããæåŠãç¶æ ã§ãåãããã«æ©èœããŸã
é²è¡ç¶æ³ã®3çªç®ã®ãã¢- éç¥ã¡ãœããã¯ãç¶æ ãå€æŽããã«æ©èœããŸãã éç¥ãåŒã³åºããšããã¹ãŠã®é²è¡ç¶æ³ãã³ãã©ãŒãæ©èœããã ãã§ãã
promiseïŒïŒãªã©ã®ä¿è·çãªãã®ããããŸãã ãå²ç€Œã延æãããŠããªãã«æ»ããŸãã ãã³ãã©ãŒããã³ã°ïŒå®äºã倱æãé²è¡ïŒãããããšã¯ã§ããŸãããç¶æ ãå€æŽããããšã¯ã§ããŸããã ããã$ .getãè¿ããã®ã§ãã ãããŠåœç¶ã®ããšã§ãããªããajaxãªã¯ãšã¹ãã®ç¶æ ãæåã§å€æŽããå¿ èŠãããã®ã§ããïŒ
ã³ãŒããç解ããããã«ã$ .whenãåŠçããã®ãè¯ãã§ãããã ããã¯ãé 延ãªããžã§ã¯ãã®ãçµåãã§ãã 次ã®ããã«æ©èœããŸãã
var def = $.when(a, b, c ....); // "" deferred def.done(function(){ alert('resolved'); // 1 , , deferred resolve }); def.fail(function(){ alert('got error'); // 1 , deferred reject }) def.progress(function(){ alert('some error'); // , deferred notify })
$ .whenã䜿çšããå Žåãè€åãªããžã§ã¯ãã«ãã£ãŠãã³ãã©ãŒã«æž¡ãããåŒæ°ã«æ³šæããŠãã ããã 圌ã¯ããããèç©ããŸãã ã€ãŸã é¢æ°a.resolveïŒ1ïŒããã³b.resolveïŒ2ïŒãåŒã³åºãããå Žåãè€åãªããžã§ã¯ãã®done-listenerã¯åŒæ°ãšããŠ1ã2ãåãåããŸãã ããªãã¯ãã€ãªãªã³ãæŒå¥ããããšãã§ããŸãã
ãããã ããã§ããŸãã¯å°ãªããšãããã§ãæ®ã眮ãã«ã€ããŠèªãããšããå§ãããŸã ã
éåžžã«æ¡ä»¶ä»ãã§ãç¶æ³ã¯æ¬¡ã®ããã«èª¬æããããšãã§ããŸãïŒãµãŒããŒã«ããŒã¿ãæ°åéä¿¡ããæ©èœãå®è¡ãïŒãã¡ã€ã«ããšã«1åïŒãåã»ã³ãµãŒãæ®ãïŒæ®ã眮ãïŒããããã®ã»ã³ãµãŒããã€ã³ãžã±ãŒã¿ãŒãåãåºããŸãïŒçŽæïŒã 3ãã£ã³ãã«ã®ã»ã³ãµãŒãšã€ã³ãžã±ãŒã¿ãŒããããŸãã
çµéšè±å¯ãªæ³šææ·±ãèªè ã¯ããã§ã«ãBaïŒ ã ãããããã¯çŸ©åã®é£éã§ãïŒããããŠããã§ããããã¯100ïŒ æ£ããã§ãããïŒJSã®ç¹æ§ãšããããã£ãšç°¡åã«ããããšããé¡æãèæ ®ã«å ¥ããŠïŒã æçè«è ã¯ãåãjsã®ãã¿ãŒã³ããããããã«æµåããŸãã ããããç§ãã¡ã¯ãããã«è³ãåŸããŸãããä»ã®äœããç§ãã¡ã«ãšã£ãŠéèŠã§ããã¿ã¹ã¯ã®æ¡ä»¶ããèžããåžžèã«å°ãããŠãç§ãã¡ã¯èªåã§ãã¿ãŒã³ã®å®çŸã«ã»ãšãã©éããŸãããã€ãŸããããã«ã€ããŠå°ãèªãã§ã ã
1ã€ã®åé¡ã解決ããªãã£ãå Žåãåé¡ã解決ããããã®èš±å®¹å¯èœãªæ¹æ³ãèŠã€ããŸããã ç§ãã¡ã«ã¯äœãæ®ã£ãŠããŸããïŒ ãã¡ã€ã«ãèªã¿åãã¿ã¹ã¯ããããŸãã ãã©ãŠã¶ãŒã®æ©èœã«å¿ããŠãå ¥åã§éžæããããã¡ã€ã«ã®ãªããžã§ã¯ããååŸãããããã©ã«ããŒã®å 容ãèªã¿åãããšãã§ããŸãïŒå¿ èŠã«å¿ããŠååž°çã«ïŒã ãŸãã¯ãäœãã§ããŸããïŒãã©ãŠã¶ãæšæž¬ããŸãïŒ-å ¥åããã ãã§ãã ããã«åãããš-äžé£ã®ãªãŒããŒïŒäžé£ã®è·åïŒã圢æããé©åãªæ©èœãéžæããããšã§ãããå埩ããããšããèŠæãçããŸãã ããããã¹ãŠUploadsãªããžã§ã¯ãã«å ¥ããŸãã ããã¯æ¬¡ã®ããã«ãªããŸãã
Uploader = _responsibilityChain: (options, chain, name = false)-> stream = false $.each chain, (i, func)=> if stream = func(options) # Uploader # @[name] = func if name false stream readers: [entry, file, input] read: (options)->@_responsibilityChain options, @readers, 'read' senders: [xhrFile, formDataFile, formDataForm, iframe] send: (options)->@_responsibilityChain options, @senders, 'send'
ãã®ã¡ã«ããºã ã®å®è£ ã¯ãUploaderã®å¥ã®æ©èœã§å®è¡ãããŸããã ãããŠãã€ãã¬ãŒã·ã§ã³ã®ããå åŽã§ãUploaderãªããžã§ã¯ãã«å¿ èŠãªã¡ãœããïŒèªã¿åããŸãã¯éä¿¡ïŒãšããŠæ¥è¿ããé¢æ°ãèšå®ããŸãã 次ã«ãèªã¿åãé¢æ°èªäœãïŒã³ã¡ã³ããšãšãã«ãã©ã°ã€ã³ã³ãŒãããããå€ãã®ç¯å²ã§ïŒèŠãŠã¿ãŸãããã
# input = (options)-> return false unless options.input.value $.Deferred().resolve([]).promise() # - input # , Deferred 3- file = (options)-> files = $.makeArray $(options.input).prop 'files' return false unless files.length if (files[0].name == undefined && files[0].fileName) # File normalization for Safari 4 and Firefox 3: $.each files, (index, file)-> file.name = file.fileName; file.size = file.fileSize; $.Deferred().resolve(files).promise() # -reader. . , .. # Deferred. , entry = (options)-> roots = $(options.input).prop('webkitEntries') || $(options.input).prop('entries') return false unless roots && roots.length > 0 readEntries = (entries, path='')-> $.when.apply($, $.map entries, (entry)-> dfd = $.Deferred() errorHandler = (e)-> e.entry = entry if e && !e.entry # Since $.when returns immediately if one # Deferred is rejected, we use resolve instead. # This allows valid files and invalid items # to be returned together in one set: dfd.resolve [e] resolveHandler = (file)-> # Workaround for Chrome bug #149735 file.relativePath = path dfd.resolve file if entry.isFile entry._file && resolveHandler(entry._file) || entry.file resolveHandler, errorHandler else if entry.isDirectory entry.createReader().readEntries((entries)-> readEntries(entries, path + entry.name + '/' ).done((files)->dfd.resolve files ).fail(errorHandler) , errorHandler) else # Return an empy list for file system items other than files or directories: dfd.resolve([]); dfd.promise() #we do need this pipe here bc we do resolve some files scoped ).pipe -> Array.prototype.concat.apply [],arguments readEntries(roots).promise()
èŠããã«ãåé¢æ°ã¯ç¬èªã®æ¹æ³ã§ãªãã·ã§ã³ããã®å ¥åãã¬ã€ãããé 延ãã¡ã€ã«ãè¿ããŸããããã¯ãèªã¿èŸŒãŸãããã¡ã€ã«ã®ãªã¹ãã§èœã¡çããŸãã
ç±å¿ã§çµéšè±å¯ãªèªè ã¯ãããã®ã©ããã§ããã®ãã¿ãŒã³ã§ã¯ãªãïŒããšå«ã¶ã¹ãã§ãã ãããŠåã³ãããã¯100ïŒ æ£ããã§ãããã å éšã®ããã°ã©ããŒã¯ãããã§äœãããããããšæããŠããŸãã äžéšã®ãªãŒããŒã®äœæ¥ã®çµæã¯ããã¹ãŠã®éä¿¡è ã«éä¿¡ããããã«éä¿¡ããããšã¯ã§ããŸããïŒããšãã°ãå ¥åãªãŒããŒã®åŸãxhrFileéä¿¡è ã¯éä¿¡ã§ããŸããïŒã ãŸãã圌ããšãŽããªã³ã ãã®ç¶æ³ã¯ãäžé©åãªéä¿¡è ã®falseãè¿ãããšã§åŠçãããŸãã ããããéä¿¡è ã®å éšã®å ¥åããããŒã¿ãçŽæ¥èªã¿åãããšã¯æ°·ã§ã¯ãããŸãã-å¿ããªãã§ãã ããããŸã Drag'n'DropããããŸããïŒ ä»ã®ãšããããã®ãŸãŸã«ããŠãããŸããããçªç¶å¥è·¡ãèµ·ãããã³ã¡ã³ãã«è³¢æãªã¢ããã€ã¹ã衚瀺ãããŸããïŒ
ãã1ã€ã®æ³šæ-å ¥åãªãŒããŒã¯äœãããŸãã-空ã®é åã§å»¶æãããé 延ãè¿ããŸãã ããã¯åãªãããã©ã«ãå€ã§ãããUploader.readå ã§ãã®æ©èœã転éã§ããŸãã çŸããã®ããã«æ®ããã-ãããåäžã
ããã«-èªã¿åããšéä¿¡ããªã³ã¯ãããªãã·ã§ã³ã®ããã©ã«ãå€ãè¿œå ããå¿ èŠããããŸãã ããäžåºŠãUploaderãªããžã§ã¯ãã«é¢æ°ãæ¿å ¥ããŸãã
Uploader: #... , upload: (options)-> options = $.extend method: 'POST' name: options.input && options.input.name , options @read(options).then (files)=>$.when.apply $, @send $.extend options, files:files
ããã§ã¯ãã¹ãŠãç°¡åã§ã-å ¥åãããã¡ã€ã«ãèªã¿åããååŸããå€ããªãã·ã§ã³ã«è¿œå ããUploader.sendã«éä¿¡ããããã®çµæãªããžã§ã¯ããè¿ããŸãã sendããåä¿¡ããé 延ãªããžã§ã¯ãã¯ããã€ãã€ã§ãã°ã«ãŒãåãããã¯ã©ã€ã¢ã³ãã«ã°ã«ãŒãåãããé 延ãªããžã§ã¯ããæäŸããŸãã
ãã¹ãŠã®äœ¿çšæ¹æ³ïŒ
$('#some-file-input').change -> Uploader.upload(input: this, url: '/files/upload' ) .done -> # alert "#{arguments.length} files uploaded" .fail -> # alert "Some files were not uploaded" .progress -> # (~ 50 ), console.log arguments
ãŸãšã
ã¢ããããŒããŒå
šäœ
Senders = _makeForm: (options)-> $('<form>', method: options.method, enctype:'multipart/form-data' ).append(options.input.clone()) _sendData: (options, data, file)-> xhr = new XMLHttpRequest() dfd = $.Deferred() xhr.onload = xhr.onerror = ->dfd[@status == 200 && 'resolve' || 'reject'] @response, file if xhr.upload xhr.upload.onprogress = (e)->dfd.notify e, file else options.no_progress = true xhr.open options.method, options.url + '?name=' + (options.file_name || file.name), true xhr.responseType = 'text' xhr.send data dfd.promise() iframe: (options)-> return false unless options.input && options.input.value options.no_progress = true id = 'frame' + Math.random() $form = Senders._makeForm(options).attr target: id, action: options.url $('<iframe>', name: id ).appendTo($form).on 'load', -> try response = @contents() throw new Error unless response.length && response[0].firstChild dfd.resolve response, name: options.input.value catch e dfd.reject response, name: options.input.value $form.submit() (dfd = $.Deferred()).promise() formDataForm: (options) -> return false unless options.input && options.input.value && window.FormData form = options.input.form || Senders._makeForm(options).get 0 Senders._sendData options, new FormData(form), name: options.input.value formDataFile: (options)-> return false unless options.files && options.files.length && window.FormData options.files.map (f)-> formData = new FormData() formData.append options.name, f Senders._sendData $.extend(options, file_name:f.name), formData, f xhrFile : (options)-> return false unless options.files && options.files.length && window.ProgressEvent && window.FileReader $.map options.files, (file)-> Senders._sendData options, file, file Readers = input: (options)-> return false unless options.input.value $.Deferred().resolve([]).promise() file: (options)-> files = $.makeArray $(options.input).prop 'files' return false unless files.length if (files[0].name == undefined && files[0].fileName) # File normalization for Safari 4 and Firefox 3: $.each files, (index, file)-> file.name = file.fileName; file.size = file.fileSize; $.Deferred().resolve(files).promise() entry: (options)-> roots = $(options.input).prop('webkitEntries') || $(options.input).prop('entries') return false unless roots && roots.length > 0 readEntries = (entries, path='')-> $.when.apply($, $.map entries, (entry)-> dfd = $.Deferred() errorHandler = (e)-> e.entry = entry if e && !e.entry # Since $.when returns immediately if one # Deferred is rejected, we use resolve instead. # This allows valid files and invalid items # to be returned together in one set: dfd.resolve [e] resolveHandler = (file)-> # Workaround for Chrome bug #149735 file.relativePath = path dfd.resolve file if entry.isFile entry._file && resolveHandler(entry._file) || entry.file resolveHandler, errorHandler else if entry.isDirectory entry.createReader().readEntries((entries)-> readEntries(entries, path + entry.name + '/' ).done((files)->dfd.resolve files ).fail(errorHandler) , errorHandler) else # Return an empy list for file system items other than files or directories: dfd.resolve([]); dfd.promise() #we do need this pipe here bc we do resolve some files scoped ).pipe -> Array.prototype.concat.apply [],arguments readEntries(roots).promise() Uploader: _responsibilityChain: (options, chain, name = false)-> stream = false $.each chain, (i, func)=> if stream = func(options) # Uploader # @[name] = func if name false stream readers: [entry, file, input] read: (options)->@_responsibilityChain options, @readers, 'read' senders: [xhrFile, formDataFile, formDataForm, iframe] send: (options)->@_responsibilityChain options, @senders, 'send' upload: (options)-> options = $.extend method: 'POST' name: options.input && options.input.name , options @read(options).then (files)=>$.when.apply $, @send $.extend options, files:files
å ¥å[type = file]ã®è¡šç€ºã«é¢ããåé¡ã®è§£æ±ºçãšããŠããã®ãããªããªãã¯ãææ¡ããŸã-äœçœ®ã䜿çšããŠå ¥åèªäœãé衚瀺ã«ããŸãïŒã³ã³ããã®ç«¯ãã¯ããã«è¶ ããŠãã©ãã«ãå®ååããŸãã
å°ãããç°¡åã«æ¡åŒµå¯èœãªãã¡ã€ã«ã¢ããããŒããŒããããŸãã æ°ããã¢ããããŒãã¡ã«ããºã ã衚瀺ãããããéä¿¡è ãšããŒã«ã®ãœãŒãæžã¿ãªã¹ãã«ç°¡åã«è¿œå ããŸãã é¢æ°éãçµã¶ããŒã¿ã®åœ¢åŒã¯åºå®ãããŠããã$ .Deferredã§ãã ãããïŒ
-åæããŠã³ããŒãæ°ã«å¶éã¯ãããŸãã
-ããŠã³ããŒããã£ã³ã»ã«ã¡ã«ããºã ãªã
-ã¯ã©ã€ã¢ã³ãåŽã§ã®äžå¿«ãªã€ãã³ã-ã€ãã³ãããã¡ã€ã«ãã¢ããããŒããããŸããããããã¡ã€ã«ãšã©ãŒãããããŸãã é²è¡ç¶æ³ã€ãã³ãã«ã¯ãããŠã³ããŒãããããã¡ã€ã«ã®æ°ã確èªããçµã¿èŸŒã¿æ©èœã¯ãããŸãã
èå³æ·±ãå Žåã¯ãæ¬ ç¹ïŒããã³å©ç¹ïŒãåãé€ãæ¹æ³ã瀺ããŸãã ããã§ãç§ã¯ç§ã®äŒæãããŒã«ãããã·ã¥ãé£äººãåãããŠãã ããã
䜿çšãããæç®ã®ãªã¹ãïŒ
1. jQuery-File-Uploadãã©ã°ã€ã³ã³ãŒã-github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.fileupload.js
2. jQuery.Deferredããã¥ã¡ã³ã-api.jquery.com/category/deferred-object
3.æ¬ããã¶ã€ã³ãã¿ãŒã³ã Freemanov-www.ozon.ru/context/detail/id/20216992