JavaScriptで非同期処理の途中で中断したいよぉお
JSDeferredのcancelだと目的のことはできなくて、それは構造上無理なんだろうなーと。
で、こんなのを書いてみたものの使いにくい。
https://gist.github.com/1200041
function Trampoline(func) { this.task = new Task(func); } Trampoline.prototype.step = function() { if (!this.task) return; this.task = this.task.cont(); if (this.task) this.task.nextStep = this.step.bind(this); }; Trampoline.prototype.cancel = function() { if (this.task && this.task.canceler) { this.task.canceler(); } this.task = null; } function Task(cont) { this.cont = cont; this.nextStep = null; this.canceler = null; } Task.prototype.getCallback = function() { var self = this; return function() { self.nextStep() }; }; function wait(cont, sec) { var task = new Task(cont); var timerId = setTimeout(task.getCallback(), sec * 1000); task.canceler = function() { clearTimeout(timerId) }; return task; } function f1() { console.log(1); return wait(f2, 1); } function f2() { console.log(2); return wait(f3, 1); } function f3() { console.log(3); return null; } var trampoline = new Trampoline(f1); trampoline.step(); setTimeout(function () { console.log("cancel!"); trampoline.cancel(); }, 1500);
で、どうやらMochiKitのDeferredなら目的のことができるみたい
https://gist.github.com/1202768
function main() { var d = accessAndShowEntries(); d.addCallback(function() { console.log("finish"); }); setTimeout(function() { console.log("cancel!"); d.cancel(); }, 2500); } function accessAndShowEntries() { function loop(i) { if (i >= 5) return; return accessEntry(i).addCallback(function (data) { console.log(data); return callLater(0, loop, i + 1); }); } return callLater(0, loop, 0); } // XHR で何かアクセスする代わり function accessEntry(i) { var d = new Deferred(); var cb = d.callback.bind(d, "foo"+i); var timerId = setTimeout(cb, 1000); d.canceller = function () { clearTimeout(timerId); }; return d; }
でも、JSDeferredの超絶シンプルさに比べてMochiKitのDeferredは複雑だなー。ちょっと理解しようとする気力が起きない
それから、DeferredListのcancelを呼んでも、list全部のcancelを行うっていうふうになっていないのが不思議。なんでだ?
余談
ちなみに動機はTumblrでlikeしておいたものをまとめて自動でリブログと画像の保存をするっていう変なvimperatorプラグイン https://gist.github.com/1194341
(全く関係のない話で、このプラグインは新しいタブを開いてそこのdocumentにあれこれ書き込むっていうのをやっていてなんだかマズそう。実際このタブで別のページを開くとなぜか書き込んだ要素が残っていたりするし...)
これに処理の途中で中断できるボタンとか、タブを閉じようとしたときに中断できる機能をつけたいと思ったのだ。
ところで、Vimperatorプラグインで_libly.js以外ではなにかライブラリを使っているコードとかほとんど見かけないんだけどライブラリを使うときはどうすればいいだろう...ライブラリのコードをソースに含めちゃうとか、あらかじめファイル名の先頭にアンダースコアをつけてプラグインディレクトリに保存してねって形にするとか?
でももう疲れちゃってやる気なくなったからもういいやー感