Atomのプラグインを書こうとして,CoffeeScriptを書いていたらPromiseの使用中にハマった.
もう既に誰かが踏んだ地雷な気がするし,Qiitaに記事があると思ったが,見つからなかったのでメモがてら残しておく.
やりたい事とコード
CoffeeScriptを使って,次のようなPromiseの使用をしたかった.
-
thenの引数関数内で,メンバへのアクセスをする -
thenの引数関数内で,resolve,rejectを使う
then内で,非同期APIの結果の例外処理(JSON,DOMのパースなど)をして,さらに,成功時はメンバへアクセスして処理をするような感じで,例えば,次のようなコード(Promiseの必要がないコードだが,例という事で)
class Class
n: 2
func: ->
new Promise(
(resolve) -> resolve(10)
).then(
(value) ->
if value is 0
reject("value is 0")
else
resolve(value * @n)
).then((value) -> console.log(value + " #result"))
が,これを動かすと,@nがundefinedとなり(CoffeeScriptの仕様への自分の理解が正しければ当然),コンソールにはNaN #resultが表示されてしまう.
こういうcallbackを簡単にかくために,CoffeeScriptには=>という記法があるので,これを使うと次のように書ける.
class Class
n: 2
func: ->
new Promise(
(resolve) -> resolve(10)
).then(
(value) =>
if value is 0
reject("value is 0")
else
resolve(value * @n)
).then((value) -> console.log(value + " #result"))
しかし,今度はUncaught (in promise) ReferenceError: resolve is not definedというエラーメッセージが表示される.
あまりちゃんと調べていないが,resolveは,this.resolveの意味であり,=>によってthisの動きが変わっているのだろう.
実験
どういうふうに書けば適切な動作をするのかを調べるべく,書き方を思いつく限り試して見た所,次のような結果になった.結局,new Promiseを使って記述するのが今回の場合は最善なのかな.
上手く動くコード
then((value) -> value)
then((value) => value * @n)
then((value) => new Promise((resolve, reject) => resolve(value * @n))
メンバにアクセス出来ずに変な動作をするコード
then((value) -> value * @n)
ReferenceErrorが起こるコード
(value) => resolve(value * @n)
最後に
他にもっと簡単な解決策があれば教えて頂けると嬉しいです.CoffeeScriptは触り始めたばっかりなので.