Promise.resolve(42)
.then(val => console.log(val));
Promise は JavaScript で非同期操作を処理するための一般的な方法です。Promise メソッドを呼び出すことで、ClojureScript でも簡単に使用できます。
JavaScript
Promise.resolve(42)
.then(val => console.log(val));
ClojureScript
(.then (js/Promise.resolve 42)
#(js/console.log %))
ただし、ClojureScript で Promise メソッドをチェーンすると、コードがカスケードされます。スレッドファーストマクロを使用すると、よりエレガントなコードに戻ることができます。
JavaScript
Promise.resolve(42)
.then(val => console.log(val))
.catch(err => console.log(err))
.finally(() => console.log('cleanup'));
ClojureScript
(.finally
(.catch
(.then (js/Promise.resolve 42)
#(js/console.log %))
#(js/console.log %))
#(js/console.log "cleanup"))
; same as above
(-> (js/Promise.resolve 42)
(.then #(js/console.log %))
(.catch #(js/console.log %))
(.finally #(js/console.log "cleanup")))
awaitを使用する Promise の重いコードは、あまり使い勝手の良くない、より複雑なコード構造になります。Puppeteer の使用方法の次の例をご覧ください。
JavaScript
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
} catch (err) {
console.log(err);
}
await browser.close();
})();
ClojureScript
(def puppeteer (js/require "puppeteer"))
(-> (.launch puppeteer)
(.then (fn [browser]
(-> (.newPage browser)
(.then (fn [page]
(-> (.goto page "https://clojure.dokyumento.jp")
(.then #(.screenshot page #js{:path "screenshot.png"}))
(.catch #(js/console.log %))
(.then #(.close browser)))))))))
このようなコードを制御するために、core.asyncに目を向けます。
ClojureScript には、core.asyncという優れた非同期プログラミング機能が用意されています。特に便利なツールの 1 つである<p!マクロは、goブロック内で Promise を消費します。
goブロックを使用すると、JavaScript でawaitとasyncが実際の非同期操作でも同期操作のように見えるコードを書くことができます。
ClojureScript
(:require
[cljs.core.async :refer [go]]
[cljs.core.async.interop :refer-macros [<p!]])
(def puppeteer (js/require "puppeteer"))
(go
(let [browser (<p! (.launch puppeteer))
page (<p! (.newPage browser))]
(try
(<p! (.goto page "https://clojure.dokyumento.jp"))
(<p! (.screenshot page #js{:path "screenshot.png"}))
(catch js/Error err (js/console.log (ex-cause err))))
(.close browser)))
これはほんの序の口です。core.asyncには、単一の Promise を処理する以上の機能を持つ非常に強力なキューのようなチャネルがあります。
リポジトリ、理論、コードウォークスルー、ブログ記事でcore-asyncについて詳しく読むことができます。
元の作者: Filipe Silva