JavaScriptってシングルスレッドしかできなかと思ってた

それゆえにpromiseとか、async/awaitとかの非同期処理のための機能が用意されているのですが、

① ブラウザならばWeb Worker:一部制限はあるけれどもマルチスレッド動作ができる。こういう機能無かったらブラウザでのマルチスレッド処理は著しく不便になりそう、元々ブラウザは同時にたくさんのスレッドが動いているし、

スレッド間通信(postMessage/onmessage API)はevent emitterのemit/onと類似だし、Golangのチャネルとも似ていますが、安全に通信(スレッド間)を行おうとするとこのようなAPIが必要になるのはどの言語でも共通でしょう。

② Node.jsならば子プロセス、マルチスレッドのためにはworker_threadというAPIが用意されているようです。子プロセスなのでスレッドよりもリソースの分離性は良くなるでしょう、負荷は高くなりそうですが。

プロセス間通信はsend/on APIを使うのはWeb Workerとも類似だし、子プロセスの起動にforkを使うのもほぼそうだろうと思います。

個人的にはNode.jsではマルチスレッド(プロセス)を使ってみる機会がありそうです。

 

admin

AppleScript

初めて知りましたが、MacでAppleのスクリプト言語(OSA : open scripting architecture対応)を使えばJavaScriptの実行も呼び出せるということ。

例えば、以下のようなhello.jsファイルを実行するには、

let helloWorld = "Hello World";

console.log(helloWorld);

----------------------------------
% osascript -l JavaScript hello.js
Hello World

のように呼び出せます。一番簡単に使えるJavaScriptの実行環境になるかと思います。もちろんDOMなどの呼び出しはできませんが。

osascriptのコマンド使用方法は、

https://support.moonpoint.com/os/os-x/man/man_osascript.html

node.jsがインストールされていれば、その環境で実行するのが一番確実ではありますが。

 

admin

Node.js(JavaScript)で経過日(時間)を求める

GolangにはtimeパッケージにYearDay()という年初からの連続で今日が何日目かを返してくれる関数があってそれをファイル名(tbl + 西暦年 + 連続何日目)に使っています。1日に2個以上テーブル作る可能性がないから、これで一意にファイル名を決定できます。

https://pkg.go.dev/time

でもNode.jsで同じファイル名を指定しようとするとこのような関数はないので、計算が必要になります。なぜNode.jsで必要かというとGolangで作成したSQLiteのテーブルにNode.jsからアクセスしたいからですが。

Golangでのテーブル作成、年号と年初からの経過日でファイル名を作成しています。以下のコードの一番下の行でターブル作成。

date := strconv.Itoa(t.Year()) + strconv.Itoa(t.YearDay())

	if del {
		cmd := "drop table if exists tbl" + date

		_, err := db.Exec(cmd)
		if err != nil {
			fmt.Println("db table drop error")
		}
	}

	// table exist check
	cmd := "select*from tbl" + date
	_, table_check := db.Query(cmd) // checked by using return code

	if table_check != nil {

		cmd = "create table if not exists tbl" + date + "(id string primary key, name, time int, stat int)"

JavaScriptでのテーブル名の作成スクリプト

// calc file name
let d = new Date();
let year = d.getFullYear();
let month = d.getMonth();
let day = d.getDate();

let date1 = new Date(year, 0, 0);
let date2 = new Date(year, month, day)
let behind = Math.floor((date2 - date1) / (24*3600*1000));      // convert milisec to day


db.serialize(() => {
    db.each("select * from tbl" + year + behind + " where stat=0", (err, row) => {
    console.log(`${row.id} ${row.name} ${row.time} ${row.stat}`);
    })
});

Math.fllor():端数切り捨てはなくても大丈夫のようですが、入れておいて実害はないだろうから。

 

admin

Node.jsでSQLiteにアクセス

Golangで作成したSQLiteのテーブルをnode.jsからアクセスしてみようと思ったが、前提になるnpmが起動できないし、nodeも起動できない。

% node   

dyld[71646]: Library not loaded: /opt/homebrew/opt/icu4c/lib/libicui18n.71.dylib

  Referenced from: <66A3E1EC-93E2-36D1-889D-02EE5C192FCC> /opt/homebrew/Cellar/node/18.11.0/bin/node

Reason: tried: ‘/opt/homebrew/opt/icu4c~~~~以下省略

解決方法は、

https://stackoverflow.com/questions/53828891/dyld-library-not-loaded-usr-local-opt-icu4c-lib-libicui18n-62-dylib-error-run

から、

% brew reinstall icu4c

で解決。

・Node.jsからSQLiteへアクセスするドライバーをインストール

% npm install sqlite3

・すでに存在しているテーブルにアクセスしてみる、

//

// DB handler

//

'use strict';

const sqlite3 = require("sqlite3");

const db = new sqlite3.Database("./myfare.db");

db.serialize(() => {

    db.each("select * from tbl202382 where stat=0", (err, row) => {

    console.log(`${row.id} ${row.name}`);

    })

});

db.close();

do.run()が非同期実行なのでsierialize()が必要とのことですが、データ更新してなくて読んでるだけで並行処理されるものがないから実はserialize()はこのケースでは不要。

しかし実行すると、

Error: Cannot find module ‘sqlite3’

対策はパスを通すことらしいので、

% export NODE_PATH=`npm root -g`

で、

% echo $NODE_PATH

/opt/homebrew/lib/node_modules

にsqlite3は存在していますが、

% which sqlite3

とは違うディレクトリなので実はシンボリックリンクを使っているのかもしれない。

ともかくもSQLite3のテーブルアクセスはできた。

Nodeと関連技術

Nodeに関連して検索したサイトと自分用のメモです。

 

○ WebSocketのURL形式

通信時に指定するURLは、

ws://www.sample.com、あるいはセキュア接続ならwas://www.sample.com

明に使うことはあまりないだろうけども

 

○ Node.jsでソケット通信

<socket.ioのインストール>(アプリを作成するディレクトリで)

% npm install socket.io 

もはやdgramはインストール不要らしい

 

○ websocket動かすには

Node.jsとExpressの他にwsライブラリのインストールも必要、本当?

<HTTP serverとclientサンプル>

socket.ioを使った、

以下の二つはGitHubのサンプル動かしているのでセット

https://qiita.com/kouji0705/items/cf16044c7d825d09d707

https://github.com/neroneroffy/webSocketDemo

https://ai-soldier.work/websocket-node-ws/#

これ動かしてみたけど、ラズパイでも軽快に動く

 

○ Express

<documents>

https://expressjs.com

<解説>

https://qiita.com/mml/items/3cc90479df033c0998e4

https://qiita.com/ganyariya/items/85e51e718e56e7d128b8

<起動>

$ npm start

 

○ pug(HTMLテンプレート)について

<pugの概要>

https://and-ha.com/coding/what-is-pug/

こんなこともできる(markdownをincludeしてHTML出力)

https://ytyaru.hatenablog.com/entry/2018/05/01/000000

<pugの拡張>

https://qiita.com/zenno04/items/d16f881170170b567b16

Template Inheritance

https://pugjs.org/language/inheritance.html

 

○ wsサーバーの起動

Express serverとWebSocket severそれぞれ別に起動で良い

$ node ws_server.js

実際の運用は起動スクリプトに書くから個別起動で問題ない

 

○ Javascript(chart.js)でグラフ作成

json使いましょう

https://www.web-development-kb-ja.site/ja/javascript/chartjsでjsonデータを表示する/833307193/

 

○ JSからEJSへ

https://fukuno.jig.jp/2819

use strict : ESM(ES module)有効なら指定不要だったよね

 

admin

TypeScriptを使ってみる

TypescriptはMicroSoftの開発で今はオープンソースになっていて、大規模プロジェクトで使えるJavaScript上位互換のある「コンパイラ言語」、JavaScriptに型定義などの機能を付加した上位互換なので、JavaScriptの既存ソースはそのまま使えます。

 

<TypeScriptとは何か>

https://qiita.com/EBIHARA_kenji/items/4de2a1ee6e2a541246f6

コードがある程度以上の規模になったら、スクリプト言語で直接実行は辛くなるから、事前にコンパイルで基本的な文法をチェックしてくれる方がありがたいし、それ以外にもinterface, class, type alias, genericなどの大規模プロジェクト向けの拡張機能が使えます。

 

<VScodeで使うための設定>

VScodeとの相性が良いから、この環境で使うのが良いだろう。

https://qiita.com/masakinihirota/items/7ee5c2aa405c2b37d1c5

tsc : コンパイラー

ts-node : jsファイルを作成しないで直接実行、VScodeで実行するとjsファイルを作成しないからts-nodeが動いています。

それぞれの版数、

% ts-node -v

v10.9.1

% tsc -v

Version 4.8.4

 

一番シンプルなコード例、

// .js is a compiled file
// $ tsc ts_basic.ts

function greeter_ts(person: string) {
  return "Hello, " + person;
}

let user_ts = "John";

console.log(greeter_ts(user_ts));

jsファイルにコンパイルすると、

// .js is a compiled file
// $ tsc ts_basic.ts
function greeter_ts(person) {
    return "Hello, " + person;
}
var user_ts = "John";
console.log(greeter_ts(user_ts));

tsファイルで指定した型指定は取れていて、型指定はコンパイル時だけ使用されます、letがグローバル変数にもなっていますが。

 

<実践的な使い方>

https://reffect.co.jp/html/hello-typescript-tutorial#TypeScript

基本のまとめページです

例えば、VScodeでデフォルトだとtscでコンパイルするとjsファイルが同一ディレクトリに作成されてtsファイルと重複してるとエラーメッセージが出ますが、tsconfig.jsonファイルを作成すれば、jsファイルをtsファイルとは別のディレクトリに格納できるというような実践的な記述があるので有用です。

コンパイル時のjjsファイル出力ディレクトリ設定方法は、

% tsc -init

で作成されたtsconfig.jsonファイルでコメントアウトされているoutDir部分に、

“outDir”: “j_s”,
のように設定、ここでj_sはtsファイルが存在するファイル階層に作成したディレクトリを指定しています。
以下がディレクトリ構成です、
この状態で、
% tsc
で、存在するtsファイルをj_s配下にコンパイルしてjsファイルを作成します。ファイル名を指定すると、ディレクトリ指定は有効にならないで同じディレクトリにjsファイルが作成されます。
設定の為の公式ドキュメントは以下のリンクです。

https://www.typescriptlang.org/tsconfig

GitHubのリンクは、

https://github.com/chateight/type_script

 

admin

Matter.js(物理計算エンジン)

物理計算エンジンで軽量で動くものとしてMatter.jsがあります。古典物理法則に則って物体の動きを、衝突、摩擦、重力などの要素を考慮して計算しようとするとそれらを一から作り上げるには労力ですが、それらの機能を提供した「世界」を簡単に作り上げて、物体の動きをシミレーションできるものです。

公式のサイトは、

https://brm.io/matter-js/

Getting started

https://github.com/liabru/matter-js/wiki/Getting-started#usage-example

Demo

https://brm.io/matter-js/demo/#stats

———————————————————

Tutorialのサンプルに、以下の機能を付け加えています。

① マウスコントロール追加

② 背景を透過にする(デフォルトは真っ黒)

③ オブジェクトに重力、反発係数、初速などを設定できるようにした

コードを有効にするには、Matter.jsをコピーしていずれかのディレクトリに配置してコードから呼び出すようにします。

GitHubのコードリンクは、

https://github.com/chateight/electron/tree/master/matter_case

になります。

物理計算エンジンはUnityなどにももちろん使われているわけですが、JavaScriptで「割と簡単」に扱うには良い素材ではないでしょうか。

P.S. 2022/9/16

・全てのボールに初期速度をインターバルタイム毎に与えるように変更

四角形と円とで2つの大まかなグループ分けで動くようになりました

 

admin

ScratchのようにJavaScriptで制御してみる

Scratchもブロック言語をJavascriptで解釈して実行しているようなので、ScratchでできることはJavascriptでもできるし、おそらく逆も真。

と言うことで基本的な要素だけ盛り込んだサンプルを作ってみました。

ソースコード、package.jsonはとりあえず無関係でhtmlとjsファイルの二つだけです。ネコスプライトと背景画像はIP関連が不明なのでアップしてません。

<html>

https://github.com/chateight/electron/blob/master/index.html

<java script>

https://github.com/chateight/electron/blob/master/control.js

動かしてみると、

start/stopボタンでイベントリスナー登録していますが、startボタンで関数実行時にリスナー解除して、複数押しができないようにしています。もし複数押しを可能にするとネコスプライトの動きが加速されます。複数のスレッドが走るような状況になるんでしょう。

// constnt & variables
let xmin = 0;       // set moving area
let ymin = 0;        
let xmax = 800;        
let ymax = 350;        
let x = 1;          // position integer
let y = 1;
let x_px = "";      // position string "px"
let y_px = "";
let dir_x = 1;      // moving direction
let dir_y = 1;
let int_id;         // setInterval ID
//
// interval timer start function
const tmr = () => {
    int_id = setInterval(move,20);                  // "int_id" for clear "clearInterval"
    start.removeEventListener("click", tmr);        // stop the listener
}
//
// move function
function move(){
    const pos = document.querySelector(".img1");         
    if(dir_x === 1) {
        x_px = x.toString() + "px";                   
        pos.style.left = x_px;
        x += 5;
        if(x >= xmax) {
            dir_x = 0;
            pos.style.transform = "scale(-1, 1)";       // reverse the sprite
        }
    }
    if(dir_x === 0) {                   
        x_px = x.toString() + "px"; 
        pos.style.left = x_px;
        x -= 5;
        if(x <= xmin) { 
            dir_x = 1; 
            pos.style.transform = "scale(1, 1)"; 
        } 
     } 
     if(dir_y == 1) { 
         y_px = y.toString() + "px"; 
         pos.style.top = y_px; 
         y += 5; 
         if(y >= ymax) {
            dir_y = 0;
        }
     }
    if(dir_y == 0) {     
        y_px = y.toString() + "px";
        pos.style.top = y_px;            
        y -= 5;
        if(y <= ymin) { 
            dir_y = 1; 
        } 
     } 
} 
// 
// start from here 
let start = document.querySelector(".start"); 
let stop = document.querySelector(".stop"); 
start.addEventListener("click", tmr); 
stop.addEventListener("click", () => clearInterval(int_id));

P.S. 2022/9/9

コードが冗長で見苦しいのでコンパクト化して、なおかつスプライトの向きを上下移動でも変えてみました、GitHubにのみ反映です。

Electron配下のディレクトリに作成しているので、デスクトップアプリでも動作できます。

 

admin

Wine

Electronで各プラットホーム向けの配布用のアプリを作成するのにWineのインストールが要求(具体的にはWindows用のはず)されますが、じゃWineって何?なのかというとWindows用のAPIを提供して、Windows OS以外でWindows用のアプリケーションを完全互換では無いけれども動かせるオープンソースのアプリケーションのようです。

MacbookでElectronからアプリ起動してもWineが立ち上がるようなので、使い方はいまいちリサーチ必要。

 

admin

『今時のJavaScriptを知るための本』ワンパス終了

およそ一月半前に購入の書籍、一通り読了、読むんじゃなくて自分でコード書いてみるのがポイントですが。

https://isehara-3lv.sakura.ne.jp/blog/2022/07/24/今時のjava-scriptを知るための本/

個人的にはHTMLをクライアント側で処理すると言う使い方よりは、サーバーサイドあるいはデスクトップアプリでの使い方に興味があります。

それらの使い方では動作環境としてはNode.jsになるんでしょうけれども、そもそもVScodeもNode.js使っているのは初めて知りました。従ってデスクトップアプリならElectron(開発はGitGub)の選択になるのでしょう。

Node.jsの拡張パッケージ使えばTypeScriptも扱えるようですね。

 

admin