質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

5277閲覧

javascriptの関数でブロックをしたい

koyon

総合スコア10

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

2クリップ

投稿2018/06/17 02:51

編集2018/06/17 04:11

javascriptにおいて、ある関数を排他的に使われるようにして同時に実行
されないうようにしたいのですが、どのようにしたらよいでしょうか?
完全にブロックできれば理想ですが、1秒遅延させられればそれでも十分です。

私が試したのは以下のように「実行中フラグ」みたいなのをセットしてフラグがtrueの場合はsetTimeoutで処理を1秒遅らせるというように試してみたのですが、複数呼び出すと同時に実行されてうまくいきませんでした。。

var is_processing = false; function somefunc() { var wait = 0; if (is_processing == true) { wait = 1000; } setTimeout(function() { // 処理 is_processing = true;     do_something(); }, wait); is_processing = false; }

お手数ですがご教示いただけますと助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/06/17 03:04

もう少し目的や今回の対応をやることになった経緯など書くと回答も得られやすいかもしれません。別のアプローチも提案があるかもしれませんし
kei344

2018/06/17 03:05

質問文のコードはコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
guest

回答3

0

ベストアンサー

フラグ管理

同期処理である限りは多重実行されませんが、非同期処理でしょうか。

JavaScript

1'use strict'; 2const something = ((executed) => function something () { 3 if (executed) { 4 throw new Error('something() can not be executed in duplicate'); 5 } 6 7 executed = true; 8 9 console.log('実行中'); 10 11 executed = false; 12})(false); 13 14something();

ご存知とは思いますが、変数 executed の処理中フラグは非同期処理が完了したタイミングで変更してください。

タイマー管理

回答いただいたところ恐縮なのですが、Errorを出すとその呼出が失敗してしまうかと思います。。呼び出しに対して実行はしないといけないのですが、同時に実行するのは避けたいというところなのです・・・。

setTimeout なら仕様上、排他処理されます。
実行タイミングは前処理が終わった直後ですが、期待するタイミングが異なるなら自前で制御する必要があります。

JavaScript

1function something (string) { 2 console.log(string); 3} 4 5setTimeout(something, 1000, 1); 6setTimeout(something, 1000, 2);

window.setTimeout() + Queue

どんな場面かといいますとチャットメッセージを受信して画面にappendで追加するのですが、その処理を1個ずつ追加するようにしたいのですが、ほぼ同時に関数が呼ばれるといっぺんに追加されてしまうので、それを間を置いて追加されるようにしたいのです。。

それは「同時に実行」ではなく、「処理間隔が0もしくは0に近い状態」で連続的に実行されています
関数をキュー管理してやれば、解決可能です。

JavaScript

1const setTimeQueue = ((handleTimeout) => { 2 const queue = []; 3 4 return function setTimeQueue (fn, args) { 5 queue.push({fn: fn, args: args}); 6 7 if (queue.length === 1) { 8 setTimeout(handleTimeout, 500, queue, 500); 9 } 10 }; 11})(function handleTimeout (queue, delayTime) { 12 const entry = queue.shift(); 13 14 entry.fn(...entry.args); 15 16 if (queue.length) { 17 setTimeout(handleTimeout, delayTime, queue, delayTime); 18 } 19}); 20 21const consoleLog = console.log.bind(console); 22 23setTimeQueue(consoleLog, [1]); 24setTimeQueue(consoleLog, [2]); 25setTimeQueue(consoleLog, [3]);

Re: koyon さん

投稿2018/06/17 03:02

編集2018/06/17 12:29
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koyon

2018/06/17 03:33

ご回答ありがとうございます。 回答いただいたところ恐縮なのですが、Errorを出すとその呼出が失敗してしまうかと思います。。呼び出しに対して実行はしないといけないのですが、同時に実行するのは避けたいというところなのです・・・。 ただ、 if (executed) { throw new Error('something() can not be executed in duplicate'); } の部分を、 if (executed) { setTimeout(function() { }, 1000); ・・・ } と変えて実行してみましたがやはりブロックできませんでした。 お忙しい中ありがとうございます。
think49

2018/06/17 03:52

> 回答いただいたところ恐縮なのですが、Errorを出すとその呼出が失敗してしまうかと思います。。呼び出しに対して実行はしないといけないのですが、同時に実行するのは避けたいというところなのです・・・。 では、いつ実行するのでしょうか。 > と変えて実行してみましたがやはりブロックできませんでした。 変更タイミングの問題と思います。 「変数 executed の処理中フラグは非同期処理が完了したタイミングで変更してください」と書いた通りです。
koyon

2018/06/17 04:24

ありがとうございます。 もう少し自分で試してみます。
think49

2018/06/17 04:45

結局、いつ実行するのでしょうか。 親記事の「タイマー管理」に書いたのと同じタイミングでしょうか。 なお、do_something(); が「非同期処理」なら今出ているコードだけでは対応できません(そうでないと質問が成り立たないので、非同期処理であるとは思っていますが、まだ答えを貰っていませんね…)。 do_something() の開始直前、終了直後でフラグを立てる必要がありますが、終了直後は「コールバック処理」か do_something() 内部コードに追記しなければなりません。
koyon

2018/06/17 08:23

返信が遅くなり申し訳ございません。 do_something(); と書いた部分は単にjqueryでDOMをappendするだけの処理なので非同期処理とは言えないかと思います。 関数を呼び出す側は具体的にはメッセージを受信するごとに非同期に呼び出します。 どんな場面かといいますとチャットメッセージを受信して画面にappendで追加するのですが、その処理を1個ずつ追加するようにしたいのですが、ほぼ同時に関数が呼ばれるといっぺんに追加されてしまうので、それを間を置いて追加されるようにしたいのです。。
think49

2018/06/17 11:35 編集

> どんな場面かといいますとチャットメッセージを受信して画面にappendで追加するのですが、その処理を1個ずつ追加するようにしたいのですが、ほぼ同時に関数が呼ばれるといっぺんに追加されてしまうので、それを間を置いて追加されるようにしたいのです。。 それは「同時に実行」ではなく、「連続実行されるインターバルが短い」が正しい表現ですね。 そうなると、解決へのアプローチが全く違います。 初めからそこまで詳細に書いてほしかったところです。 とりあえず、「キューに入れてsetTimeoutでインターバルを置きながら実行」で解決できます。
think49

2018/06/17 12:29

親記事に追記しました。
koyon

2018/06/18 04:47

「キューに入れてsetTimeoutでインターバルを置きながら実行」で解決しました!お忙しい中コードを書いてくださいましてありがとうございました。こんなコードは自分にはヒントをいただいても100%無理でした。 > 初めからそこまで詳細に書いてほしかったところです。 ・・・余計なお手間をかけて申し訳ありませんでした。
guest

0

javascript

1var is_processing = false; 2const wait = 1000; // <------------------- 別に定数でよい気がする 3 4function somefunc() { 5 //var wait = 0; // <------------------- 定数化したら不要 6 if (is_processing == false) { // <----- 処理中でなかったらsetTimeoutすればいいんでは? 7 setTimeout(function() { 8 // 処理 9 is_processing = true; 10     do_something(); 11 is_processing = false; // <------ 処理が終わったらflag-OFF 12 }, wait); 13 } 14 // is_processing = false; // <--------- これはいらんでしょ。 15}

投稿2018/06/17 04:56

編集2018/06/17 05:01
tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

setTimeoutした後に(タイマーセットしただけでdo_something();が実行されてないのに)
is_processing = false;してるのが問題のように思います。

最後のis_processing = false;は消して
setTimeoutは下記ではないでしょうか?

setTimeout(function() { // 処理 is_processing = true; do_something(); is_processing = false; }, wait);

投稿2018/06/17 03:49

shun-K

総合スコア508

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koyon

2018/06/17 04:05

ご回答ありがとうございます。 どうも自分はjavascriptの基本がわかっていないようです。。 setTimeout(function() { // 処理 is_processing = true; do_something(); }, wait); is_processing = false; と書くとsetTimeout(function()が実行されたあとに、is_processing = false;が実行されると思っているのですが、順番に実行されるわけではないのですね・・・? お手数おかけしております。
shun-K

2018/06/17 04:19 編集

setTimeoutは 「setTimeout(関数,待ち時間);」を実行すると 「『[関数]を[待ち時間]後に実行してね』ってタイマーセットする」だけです。 タイマーセットしただけなので[関数]はまだ実行されてません。
koyon

2018/06/17 04:27

なるほど・・もう少し勉強する必要がありまそうです。。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問