twitter のアカウントは sarabandejp と masakielastic (仕事関係)です。連絡先は masakielastic @gmail.com です。Sarabande.jpTumblr (3.0; @sarabandejp)https://blog.sarabande.jp/- Golang: ベータ版や RC 版をインストールする<p>
go 1.8、19 のベータ版や RC 版は go get コマンドでインストールできる。
</p>
<pre class="prettyprint bash">
# <a href="https://twitter.com/golang/status/894686139361120256">https://twitter.com/golang/status/894686139361120256</a>
# <a href="https://godoc.org/golang.org/x/build/version">https://godoc.org/golang.org/x/build/version</a>
go get golang.org/x/build/version/go1.9rc2
go1.9rc2 download
go1.9rc2 version
</pre>https://blog.sarabande.jp/post/163939058363https://blog.sarabande.jp/post/163939058363Tue, 08 Aug 2017 17:25:27 +0900golang
- Node.js: CGI を通して利用する<p>
h2o の CGI として node.js のスクリプトを動かしてみた。macOS の場合、<code>#!/usr/bin/env node</code> がエラーになった。
</p>
<pre class="prettyprint javascript">
#!/usr/local/bin/node
console.log('Content-type: text/plain; charset=utf-8');
console.log('');
console.log('Hello World');
</pre>
<p>
サーバーにインストールされているバージョンを調べるには次の行を追加する。
</p>
<pre class="prettyprint javascript">
console.log('Version: ' + process.version);
</pre>https://blog.sarabande.jp/post/163937909683https://blog.sarabande.jp/post/163937909683Tue, 08 Aug 2017 16:27:28 +0900nodejs
- Golang: CGI を利用する<p>
ふと h2o で Go の CGI を試したくなったので書いてみた。
</p>
<pre class="prettyprint go">
package main
import "fmt"
func main() {
fmt.Print("Content-type: text/plain; charset=utf-8\n\n")
fmt.Println("Hello World!")
}
</pre>
<p>
h2o の設定は次のとおり。
</p>
<pre class="prettyprint bash">
file.custom-handler:
extension: .cgi
fastcgi.spawn:
command: "exec /usr/local/share/h2o/fastcgi-cgi"
listen:
port: 8080
ssl:
certificate-file: /usr/local/etc/ssl/server.crt
key-file: /usr/local/etc/ssl/server.key
hosts:
"127.0.0.1.xip.io:8080":
paths:
/:
file.dir: /Users/masakielastic/public_html
</pre>https://blog.sarabande.jp/post/163914125278https://blog.sarabande.jp/post/163914125278Tue, 08 Aug 2017 03:37:17 +0900golangh2o
- Node.js: browserify の復習<p>
browserify の復習。ES2015 とそれ以降の標準をまとめて導入できる babel-preset-env、
コードを圧縮してくれるbabel-preset-babili を一緒に導入する。
</p>
<pre class="prettyprint bash">
yarn add --dev browserify babelify watchify
yarn add --dev babel-preset-env babel-preset-babili
</pre>
<p>
トランスパイルの実行は次のとおり。
</p>
<pre class="prettyprint bash">
browserify app.js -o bundle.js -t [ babelify --presets [ env babili ] ]
</pre>
<p>
watchify による監視は次のとおり。
</p>
<pre class="prettyprint bash">
watchify -v -d app.js -o bundle.js -t [ babelify --presets [ env babili ] ]
</pre>https://blog.sarabande.jp/post/162876064683https://blog.sarabande.jp/post/162876064683Wed, 12 Jul 2017 06:28:26 +0900node.jsbrowserify
- React: create-react-app によるプロジェクトのセットアップ<p>
開発に必要なツールが一通りそろっている。
</p>
<pre class="prettyprint bash">
yarn global add create-react-app
create-react-app my-app
cd my-app
yarn start
</pre>https://blog.sarabande.jp/post/162869532658https://blog.sarabande.jp/post/162869532658Wed, 12 Jul 2017 02:36:14 +0900react
- Babel 6: 2017年夏のクィックスタート<p>
npm よりも高速にダウンロードできる yarn が広まってきています。npm 5.2 で npx が導入され、package.json の scripts でサブコマンドを自分で定義する手間を省けるようになりました。
</p>
<pre class="prettyprint bash">
// <a href="https://twitter.com/masakielastic/status/884805009124212736">https://twitter.com/masakielastic/status/884805009124212736</a>
yarn add --dev babel-cli babel-preset-env
echo "class Foo {}" > app.js;
npx babel --presets env app.js
</pre>
<p>
node.js で直接スクリプトを実行するには babel-node を使います。
</p>
<pre class="prettyprint bash">
npx babel-node app.js
</pre>
<p>
babili (babel-minify) による圧縮も加えてみよう。次のコマンドでプレセットを追加する。
</p>
<pre class="prettyprint bash">
yarn add --dev babel-preset-babili
</pre>
<p>
babili による圧縮を伴うトランスパイルを実行してみよう。
</p>
<pre class="prettyprint bash">
npx babel --presets=env,babili app.js
</pre>https://blog.sarabande.jp/post/162867152348https://blog.sarabande.jp/post/162867152348Wed, 12 Jul 2017 01:10:43 +0900babel
- JavaScript: テストツールの Jest を導入する<p>
Facebook が開発している Jest を使い始めることにした。
</p>
<pre class="prettyprint javascript">
yarn add --dev jest
</pre>
<pre class="prettyprint javascript">
// sum.js
function sum(a, b) {
return a + b;
}
module.exports = sum;
// sum.test.js
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
</pre>]
<p>
テストを実行してみよう。npx は npm 5.2 で導入されたツールです。
</p>
<pre class="prettyprint bash">
npx jest
</pre>
<p>
今度は Babel を導入してみましょう。
</p>
<pre class="prettyprint bash">
yarn add --dev babel-preset-env babel-jest
</pre>
<p>
package.json には次のコードを追加します。オプションを何も指定しないのであれば babel-preset-latest と同じです。
</p>
<pre class="prettyprint javascript">
{
"babel": {
"presets": ["env"]
}
}
</pre>
<p>
sum.test.js を修正して import 文を使うようにしましょう。
</p>
<pre class="prettyprint javascript">
import sum from './sum';
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
</pre>
<p>
npx jest を実行します。
</p>https://blog.sarabande.jp/post/162864553278https://blog.sarabande.jp/post/162864553278Tue, 11 Jul 2017 23:33:01 +0900javascript
- JavaScript: 複数の Promise をまとめる<p>
Promise.all を使う。
</p>
<pre class="prettyprint javascript">
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("p1 を実行しています。");
resolve("p1");
}, 1000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("p2 を実行しています。");
resolve("p2");
}, 2000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("p3 を実行しています。");
resolve("p3");
}, 3000);
});
Promise.all([p1, p2, p3]).then(([a, ...rest]) => {
console.log(a, rest);
});
</pre>https://blog.sarabande.jp/post/162804394418https://blog.sarabande.jp/post/162804394418Mon, 10 Jul 2017 10:03:06 +0900javascript
- JavaScript: タイムアウトした処理にエラーとして扱う<p>
HTTP リクエストのように処理が一定の時間を超える場合、エラーとして扱う必要がある場合、
Promise.race を使う。Bluebird を使ったコードの例は次のとおり。
</p>
<pre class="prettyprint javascipt">
const Bluebird = require('bluebird');
const p1 = Bluebird.resolve('成功').delay(500);
const p2 = Bluebird.reject(new Error('失敗')).delay(800);
Bluebird.race([p1, p2])
.then(value => {
console.log(value);
})
.catch(value => {
console.log(value);
});
</pre>
<p>
timeout メソッドで処理時間の上限を指定することができます。
</p>
<pre class="prettyprint javascript">
const Promise = require("bluebird");
const p1 = Promise.resolve("成功").delay(300);
p1.timeout(100)
.then((value) => {
console.log(value);
}).catch(Promise.TimeoutError, (e) => {
console.log("エラー";
});
</pre>
<p>
ES2015 Promise の場合、Promise.race を使うことができます。
</p>
<pre class="prettyprint javascrpt">
const p1 = new Promise((resolve, reject) => {
setTimeout((value) => {
console.log("p1 を実行してます。");
resolve(value);
}, 700, "成功");
});
const p2 = new Promise((resolve, reject) => {
setTimeout((value) => {
console.log("p2 を実行しています。");
reject(value);
}, 500, "失敗");
});
Promise.race([p1, p2])
.then((value) => {
console.log(value);
})
.catch((value) => {
console.log(value);
});
</pre>
<p>
毎回エラー処理を書かなくてすむようにタイムアウトを指定できる Promise を返す関数を定義してみましょう。
</p>
<pre class="prettyprint javascript">
function timeout(p, ms) {
const wait = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("エラー処理をしています。");
reject(new Error("エラー"));
}, ms);
});
return Promise.race([p, wait]);
}
const p = new Promise((resolve, reject) => {
setTimeout((value) => {
console.log("p1 を実行してます。");
resolve(value);
}, 2000, "成功");
});
timeout(p, 3000)
.then((value) => {
console.log(value);
})
.catch((value) => {
console.log(value);
});
</pre>
<p>
<b>追記</b>。Promise.race を使わなくてもタイムアウトは実現できます。
</p>
<pre class="prettyprint javascript">
// <a href="https://github.com/github/fetch/issues/175#issuecomment-284787564">https://github.com/github/fetch/issues/175#issuecomment-284787564</a>
function timeout(promise, ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("タイムアウトを処理しています。");
reject(new Error("timeout"))
}, ms);
promise.then(resolve, reject);
})
}
const p = new Promise((resolve, reject) => {
setTimeout((value) => {
console.log("p1 を実行してます。");
resolve(value);
}, 2000, "成功");
});
timeout(p, 1000)
.then((value) => {
console.log(value);
})
.catch((value) => {
console.log(value);
});
</pre>
<p>
最初に resolve もしくは reject されたものが考慮され、そのほかは無視されることは次のコードでも確認できます。
</p>
<pre class="prettyprint javascript">
const p = new Promise((resolve, reject) => {
setTimeout((value) => { console.log("resolve を実行しています。"); resolve(value); }, 1000, "成功");
setTimeout((value) => { console.log("resolve2 を実行しています。"); resolve(value); }, 2000, "成功2");
setTimeout((value) => { console.log("reject を実行しています。"); resolve(value); }, 3000, "失敗");
});
p.then((value) => {
console.log(value);
})
.catch((value) => {
console.log(value);
});
</pre>https://blog.sarabande.jp/post/162789778203https://blog.sarabande.jp/post/162789778203Mon, 10 Jul 2017 02:31:26 +0900javascript
- JavaScript: setTimeout でコールバック地獄を体験する<p>
コールバック地獄のコードの例を見ると、そのままでは実行できないものばかりなので、setTimeout を題材にすることにした。
</p>
<pre class="prettyprint javascript">
let msg = "Hello";
setTimeout(() => {
console.log(msg);
setTimeout(() => {
console.log(msg);
setTimeout(() => {
console.log(msg);
setTimeout(() => {
console.log(msg);
}, 1000);
}, 1000);
}, 1000);
}, 1000);
</pre>
<p>
グローバル変数を使わずに setTimeout の第3引数で渡すなら次のようになる。
</p>
<pre class="prettyprint javascript">
const msg = "Hello";
setTimeout((value) => {
console.log(value);
setTimeout((value) => {
console.log(value);
setTimeout((value) => {
console.log(value);
setTimeout((value) => {
console.log(value);
}, 1000, value);
}, 1000, value);
}, 1000, value);
}, 1000, msg);
</pre>
<p>
Bluebird.js を使うと次のように置き換えることができる。
</p>
<pre class="prettyprint javascript">
const p = require('bluebird').resolve("Hello");
p.delay(1000)
.tap(console.log)
.delay(1000)
.tap(console.log)
.delay(1000)
.tap(console.log)
.delay(1000)
.tap(console.log)
</pre>https://blog.sarabande.jp/post/162705161668https://blog.sarabande.jp/post/162705161668Fri, 07 Jul 2017 21:00:47 +0900javascript
- JavaScript: Chrome 61 で ES2015 モジュールを使う<p>
chrome://flags/ で Experimental Web Platform features を有効にすれば ES2015 モジュールを利用できるようになりました。
type 属性の値に module を指定します。モジュールの拡張子を省略すると console.log の結果が表示されませんでした。
</p>
<pre class="prettyprint javascript">
<script type="module">
import {hello} from './hello.js';
console.log(hello());
</script>
// hello.js
export function hello() {
return 'Hello';
}
</pre>https://blog.sarabande.jp/post/162684838953https://blog.sarabande.jp/post/162684838953Fri, 07 Jul 2017 07:58:31 +0900javascript
- MacOS: ヘッドレス Chrome を使う<p>
MacOS の場合、Bash で次のエイリアスを定義する。
</p>
<pre class="prettyprint javascript">
alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
</pre>
<p>
スクリーンショットをとってみましょう。
</p>
<pre class="prettyprint javascript">
chrome --headless --disable-gpu --screenshot <a href="https://www.chromestatus.com/">https://www.chromestatus.com/</a>
</pre>
<p>
次に Node.js の chrome-remote-interface を試してみましょう。
</p>
<p>
マニュアルのコードをそのまま利用させてもらいます。
</p>
<pre class="prettyprint javascript">
const CDP = require('chrome-remote-interface');
CDP({ port:9222 }, (client) => {
// extract domains
const {Network, Page} = client;
// setup handlers
Network.requestWillBeSent((params) => {
console.log(params.request.url);
});
Page.loadEventFired(() => {
client.close();
});
// enable events then start!
Promise.all([
Network.enable(),
Page.enable()
]).then(() => {
return Page.navigate({url: 'https://github.com'});
}).catch((err) => {
console.error(err);
client.close();
});
}).on('error', (err) => {
// cannot connect to the remote endpoint
console.error(err);
});
</pre>
<p>
Node.js の chrome-launcher で Chrome を起動させてみましょう。
</p>
<pre class="prettyprint javascript">
const chromeLauncher = require('chrome-launcher');
chromeLauncher.launch({
port: 9222,
chromeFlags: ['--headless', '--disable-gpu']
}).then(chrome => {
console.log(`Chrome debugging port running on ${chrome.port}`);
});
</pre>
<p>
Chrome を終了させるには kill メソッドを呼び出します。
</p>
<pre class="prettyprint javascript">
chrome.kill().then(() => {
console.log('終了しました。');
});
</pre>
<p>
コマンドラインで Chrome を起動させるのであれば次次のようにコマンドコマンドを実行します。
</p>
<pre class="prettyprint bash">
chrome \
--headless \
--disable-gpu \
--remote-debugging-port=9222 \
<a href="https://www.chromestatus.com">https://www.chromestatus.com</a>
</pre>https://blog.sarabande.jp/post/162676933473https://blog.sarabande.jp/post/162676933473Fri, 07 Jul 2017 03:52:38 +0900macos
- JavaScript: yield で Promise を返す<p>
async/await に馴れた後でジェネレーターを再学習することにした。ジェネレーターのコードの実行には co を導入。
</p>
<pre class="prettyprint javascript">
const co = require('co');
co(function* () {
return yield Promise.resolve('成功');
})
.then((value) => console.log(value));
co(function* () {
return yield Promise.reject('失敗');
})
.catch((value) => console.log(value));
</pre>https://blog.sarabande.jp/post/162490639298https://blog.sarabande.jp/post/162490639298Sun, 02 Jul 2017 09:18:22 +0900javascript
- JavaScript: 処理を遅延させて Promise を返す<p>
Bluebird.js が用意している Promise.delay に相当する関数を自分で定義してみよう。
</p>
<pre class="prettyprint javascript">
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
delay(1000).then(() => console.log('終了'));
</pre>
<p>
delay は<a href="https://github.com/sindresorhus/delay">モジュール</a>としても配布されている。
</p>
<p>
async/await を使えば同期的な停止を使うことができる。
</p>
<pre class="prettyprint javascript">
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function run() {
console.log('開始');
await delay(3000);
console.log('終了');
}
run();
</pre>https://blog.sarabande.jp/post/162488692533https://blog.sarabande.jp/post/162488692533Sun, 02 Jul 2017 08:12:37 +0900javascript
- JavaScript: Promise.try<p>
TC39 で Promise.try が提案されている。2017年7月時点でステージ1。
通常の Promise のコンストラクターと比べて resolve と reject のコールバックを指定しなくてすむことがメリットである。次のコードスニペットですぐに試すことができる。<a href="https://github.com/tc39/proposal-promise-try/blob/master/polyfill.js">ポリフィル</a>も公開されている。</p>
<pre class="prettyprint javascript">
# <a href="https://github.com/tc39/proposal-promise-try">https://github.com/tc39/proposal-promise-try</a>
# <a href="https://twitter.com/RReverser/status/695678489937186816">https://twitter.com/RReverser/status/695678489937186816</a>
Promise.try = function(cb) { return new this(r => r(cb())) };
</pre>
<p>
まずは正常な値を扱ってみよう。
</p>
<pre class="prettyprint javascript">
const p = Promise
.try(() => "Hello")
.then((value) => console.log("then", value));
</pre>
<p>
今度はエラーを投げてみよう。
</p>
<pre class="prettyprint javascript">
const p = Promise
.try(() => {
throw new Error("Error");
})
.then((value) => console.log("then"))
.catch((error) => console.log("catch", error));
</pre>
<p>
async/await を使うと次のように書き換えることができる。
</p>
<pre class="prettyprint javascript">
async function run() {
try {
const msg = await Promise.try(() => { throw new Error("failed"); });
console.log('then: ');
} catch(error) {
console.log('catch: ', error);
}
}
run();
</pre>https://blog.sarabande.jp/post/162485593478https://blog.sarabande.jp/post/162485593478Sun, 02 Jul 2017 06:30:10 +0900javascript
- JavaScript: Promise.reject に Error のインスタンスを渡す<p>
Promise.reject には文字列以外に Error のインスタンスを渡すこともできる。
</p>
<pre class="prettyprint javascript">
const p = Promise
.reject(new Error('fail'))
.then(() => console.log('then'))
.catch(error => console.log('catch'));
</pre>https://blog.sarabande.jp/post/162480584033https://blog.sarabande.jp/post/162480584033Sun, 02 Jul 2017 03:39:27 +0900javascript
- JavaScript: Promise.prototype.finally<p>
tc39 で Promise.prototype.finally が提案されている。
</p>
<pre class="prettyprint javascript">
const p = Promise.resolve('Hello')
.then(value => console.log('then', value))
.finally(() => console.log('finally'));
</pre>
<p>
node.js で v8 のフラグを指定すれば試すことができる。
</p>
<pre class="prettyprint javascript">
node --harmony_promise_finally test.js
</pre>
<p>
async/await で書き換えると次のとおり。こちらは v8 のフラグは不要である。
</p>
<pre class="prettyprint javascript">
async function run() {
try {
const msg = await Promise.resolve('Hello');
console.log('then', msg);
} finally {
console.log('finally')
}
}
run();
</pre>https://blog.sarabande.jp/post/162479780923https://blog.sarabande.jp/post/162479780923Sun, 02 Jul 2017 03:12:10 +0900javascript
- Emscripten: C 言語のプログラムを JavaScript に変換する<p>
Emscripten は homebrew でインストールできる。
</p>
<pre class="prettyprint bash">
brew install emscripten
</pre>
<p>
バージョンをチェックしてみよう。
</p>
<pre class="prettyprint bash">
emcc -v
</pre>
<p>
設定ファイルの ~/.emscripten が生成されるので修正する。
</p>
<pre class="prettyprint bash">
# <a href="https://github.com/kripken/emscripten/issues/1723#issuecomment-242385279">https://github.com/kripken/emscripten/issues/1723#issuecomment-242385279</a>
LLVM_ROOT = '/usr/local/opt/emscripten/libexec/llvm/bin'
</pre>
<p>
再度 emcc -v を実行してエラーメッセージが表示されないことを確認する。
</p>
<p>
C 言語のファイルを用意する。
</p>
<pre class="prettyprint c-lang">
#include <stdio.h>
int main() {
printf("hello, world!\n");
return 0;
}
</pre>
<p>
コンパイルしてみよう。
</p>
<pre class="prettyprint bash">
emcc hello.c -o hello.js
</pre>
<p>
生成された hello.js を node で実行すると Hello World が表示される。
</p>
<p>
今度は C 言語で定義した関数を JavaScript で使ってみよう。まずは関数を定義する。
</p>
<pre class="prettyprint c-lang">
int add(int a, int b) {
return a + b;
}
</pre>
<p>
ビルドする際に関数の名前を指定する。
</p>
<pre class="prettyprint bash">
emcc -s EXPORTED_FUNCTIONS="['_add']" add.c -o add.js
</pre>
<p>
モジュールとして読み込み、実行してみよう。
</p>
<pre class="prettyprint js-lang">
const m = require('./add');
console.log(m._add(1, 2));
</pre>https://blog.sarabande.jp/post/162478295493https://blog.sarabande.jp/post/162478295493Sun, 02 Jul 2017 02:21:24 +0900emscriptenjavascript
- Node.js: nvm から nvs (Node Version Switcher) に乗り換える<p>
Node.js の通常版、開発版に加えて ChakraCore の通常版および開発版を利用するために nvm から nvs (Node Version Switcher) に乗り換えました。
nvm は通常版だけを扱うことを方針としており、homebrew で導入した場合とあまり変わらないというのは潜在的な不満でした。
nvs に乗り換えた理由のもう1つは Windows に対応していることです。nvm は Windows に対応していないので、
nvm-windows のような別のプロジェクトのツールを導入する必要があります。
</p>
<p>
MacOS で nvs をインストールするには次のコマンドを実行します。
</p>
<pre class="prettyprint bash">
export NVS_HOME="$HOME/.nvs"
git clone <a href="https://github.com/jasongin/nvs">https://github.com/jasongin/nvs</a> "$NVS_HOME"
. "$NVS_HOME/nvs.sh" install
</pre>
<p>
インストールした後で .profile に次のコードを追加しました。
</p>
<pre class="prettyprint bash">
export NVS_HOME="$HOME/.nvs"
. "$NVS_HOME/nvs.sh"
</pre>
<p>
nvs コマンドを実行すれば、インストールできるパッケージの選択肢が表示されますので、上下ボタンとエンターキーで選びます。
デフォルトで使うバージョンを .profile に追記しておきます。
</p>
<pre class="prettyprint bash">
nvs use node/8.1
nvs use chakracore/8.1
</pre>https://blog.sarabande.jp/post/162469878738https://blog.sarabande.jp/post/162469878738Sat, 01 Jul 2017 20:50:40 +0900node.js
- JavaScript: AsyncIterator を試す<p>
TypeScript 2.3 で AsyncIterator を試してみた。
</p>
<pre class="prettyprint javascript">
import 'core-js/shim';
function sleep(ms = 0) {
return new Promise(r => setTimeout(r, ms));
}
async function* g() {
yield 1;
await sleep(100);
yield 2;
await sleep(100);
yield 3;
}
async function f() {
for await (const x of g()) {
console.log(x);
}
}
f();
</pre>
<p>
tsconfig.json は次のとおり。
</p>
<pre class="prettyprint javascript">
{
"compilerOptions": {
"target": "es2015",
"moduleResolution": "node",
"module": "commonjs",
"lib": [
"dom",
"es2015",
"esnext.asynciterable"
]
}
}
</pre>
<p>
core-js をインストールする。
</p>
<pre class="prettyprint bash">
// <a href="https://stackoverflow.com/q/43694281/531320">https://stackoverflow.com/q/43694281/531320</a>
npm install core-js --save
</pre>https://blog.sarabande.jp/post/162432735358https://blog.sarabande.jp/post/162432735358Fri, 30 Jun 2017 21:09:36 +0900javascript