0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Javascript で天ざるそばをつくる

Last updated at Posted at 2020-08-01

天ざるそばを作るとき、天ぷらを揚げてから、そばを茹でたら、天ぷらは冷えてしまう。そばを茹でてから天ぷらを揚げたら、そばにコシがなくなってしまう。できれば同時に作って、コシのあるそばでカラッとした天ぷらを食べたい。そんなわけでJavascriptでうまい天ざるそばを作る様子をシミュレートしてみよう。

ここで、天ざるそばのレシピを振り返ってみる。

A 天ぷらをつくる
  (1) 素材準備 (5秒)
  (2) 揚げる (10秒)

B そばを茹でる
  (1) はかる (2秒)
  (2) ゆでる (7秒)
  (3) あらう (3秒)

C A,Bをもりつける (5秒)

手順としては、A->B->Cではなく、 (A|B)->C でなければ、いけない。
カッコ内は、仮の調理時間。
念のために、絵で確認しておこう。
image.png

準備

このシミュレーションでは、揚げたり、ゆでたりするそれぞれの作業を始めたときに「〜開始」、その作業が終わったときに「〜完了」と報告するようにしたい。
料理作業を次のように定義することで、要件を満たす。
まずはじめに、天ぷらをつくるA-(1)を定義する。

A-(1)
function prepare(resolve, cooking_time){
  console.log("てんぷら素材準備開始");
  setTimeout(()=>resolve("てんぷら素材準備完了+cooking_time"),cooking_time*1000)
}
function prepare_tempra(sec){return new Promise((resolve)=>{prepare(resolve,sec)});}
prepare_tempra(5).then(r=>console.log(r))

これを実行すれば、次のように出力される。

"てんぷら素材準備開始"  <- 実行直後に表示される
"てんぷら素材準備完了5"  <- 5秒後に表示される

次に、天ぷらをつくるA-(2)を定義する。

A-(2)
function fry(resolve, cooking_time){
  console.log("てんぷら揚げ開始");
  setTimeout(()=>resolve("てんぷら完了"+cooking_time),cooking_time*1000)
}
function fry_tempra(sec){return new Promise((resolve)=>{fry(resolve,sec)});}
fry_tempra(10).then(r=>console.log(r))

これを実行すれば、次のように出力される。

"てんぷら揚げ開始"  <- 実行直後に表示される
"てんぷら完了10"  <- 10秒後に表示される

これらを順番に実行すれば、天ぷらが完成する。

A
const tempra = async () => {
  await prepare_tempra(5).then(r=>console.log(r))
  await fry_tempra(10).then(r=>console.log(r))
}

これを実行すると、次のように出力される。

"てんぷら素材準備開始"  <- 実行直後に表示される
"てんぷら素材準備完了5"  <- 5秒後に表示される
"てんぷら揚げ開始"  
"てんぷら完了10"  <- 15秒後に表示される

ひとまず、天ぷら手順は、OKだ。
同様にして、そば手順を定義していく。

B
function measure(resolve, cooking_time){
  console.log("そばをはかる");
  setTimeout(()=>resolve("そば計量完了"+cooking_time),cooking_time*1000)
}

function boil(resolve, cooking_time){
  console.log("そばをゆでる");
  setTimeout(()=>resolve("そばゆで完了"+cooking_time),cooking_time*1000)
}

function wash(resolve, cooking_time){
  console.log("そばをあらう");
  setTimeout(()=>resolve("そばあらい完了"+cooking_time),cooking_time*1000)
}

function measure_soba(sec){return new Promise((resolve)=>{measure(resolve,sec)});}
function boil_soba(sec){return new Promise((resolve)=>{boil(resolve,sec)});}
function wash_soba(sec){return new Promise((resolve)=>{wash(resolve,sec)});}

const soba = async () => {
  await measure_soba(2).then(r=>console.log(r)) 
  await boil_soba(7) .then(r=>console.log(r))
  await wash_soba(3) .then(r=>console.log(r))
}

かなり、冗長ではあるが、ひとまず、A、Bが定義できた。
いよいよA、Bを同時並行で実行させたい。それで、両方とも終了したときに、C:もりつけを実行したい。
さて、どうするか?

A、Bを同時並行で実行させる部分は、次のように定義できる。

(A|B)
const tempra_and_soba = async () =>{
    let t = tempra()
    let s = soba()
    await t
    await s  
}

これが終了した後に、もりつけを実行する。

(A|B)->C
function serve(resolve, cooking_time){
  console.log("もりつける");
  setTimeout(()=>resolve("天ざるそばもりつけ完了"+cooking_time),cooking_time*1000)
}
function serve_temzarusoba(sec){return new Promise((resolve)=>{serve(resolve,sec)});}

const temprasoba = async () => {
await tempra_and_soba() 
await serve_temzarusoba(5) .then(r=>console.log(r))
}

実行結果

"そば計量完了2"
"てんぷら素材準備完了5"
"そばゆで完了7"
"そばあらい完了3"
"てんぷら完了10"
"天ざるそばもりつけ完了5"

これで、うまい天ざるが食べられる。めでたし。

おまけ

お蕎麦屋さんを作ってみました。

image.png

お客さんが食べる時間などは省略。

sobaya.js
function prepare(resolve, cooking_time){
  /*console.log("てんぷら素材準備開始");*/
  setTimeout(()=>resolve("てんぷら素材準備完了"+cooking_time),cooking_time*1000)
}

function fry(resolve, cooking_time){
  /* console.log("あげる") */;
  setTimeout(()=>resolve("てんぷら完了"+cooking_time),cooking_time*1000)
}

function measure(resolve, cooking_time){
  /* console.log("そばをはかる") */;
  setTimeout(()=>resolve("そば計量完了"+cooking_time),cooking_time*1000)
}

function boil(resolve, cooking_time){
  /* console.log("そばをゆでる") */;
  setTimeout(()=>resolve("そばゆで完了"+cooking_time),cooking_time*1000)
}

function wash(resolve, cooking_time){
  /* console.log("そばをあらう") */;
  setTimeout(()=>resolve("そばあらい完了"+cooking_time),cooking_time*1000)
}

function serve(resolve, cooking_time){
  /* console.log("もりつける") */;
  setTimeout(()=>resolve("もりつけ完了"+cooking_time),cooking_time*1000)
}

function open_shop(resolve, reject, sales_time){
  /* console.log("開店") */
  setTimeout(()=>{if (this.order==0) {resolve("お店終了"+sales_time)} else {reject("まだお客さんいるけど、お店終了"+sales_time)}},sales_time*1000)
}

function open_sobaya(sec){return new Promise((resolve,reject)=>{open_shop(resolve,reject,sec)});}

function prepare_tempra(sec){return new Promise((resolve)=>{prepare(resolve,sec)});}
function fry_tempra(sec){return new Promise((resolve)=>{fry(resolve,sec)});}
function measure_soba(sec){return new Promise((resolve)=>{measure(resolve,sec)});}
function boil_soba(sec){return new Promise((resolve)=>{boil(resolve,sec)});}
function wash_soba(sec){return new Promise((resolve)=>{wash(resolve,sec)});}
function serve_soba(sec){return new Promise((resolve)=>{serve(resolve,sec)});}

const tempra = async () => {
  await prepare_tempra(5).then(r=>console.log(r))
  await fry_tempra(10).then(r=>console.log(r))
}

const soba = async () => {
  await measure_soba(2).then(r=>console.log(r)) 
  await boil_soba(7) .then(r=>console.log(r))
  await wash_soba(3) .then(r=>console.log(r))
}

const tempra_and_soba = async () =>{
  let t = tempra()
  let s = soba()
  await t
  await s   
}

const temprasoba = async () => {
  await tempra_and_soba() 
  await serve_soba(5) .then(r=>console.log(r))
}

const zarusoba = async () => {
  await soba() 
  await serve_soba(5) .then(r=>console.log(r))
}

const sobaya = async () =>{
  console.log("開店")
  let shop = open_sobaya(90).then(r=>console.log(r)).catch(r=>console.log(r))
  
  console.log("一人目")
  order=1
  await temprasoba()
  order=0
  console.log("二人目")
  order=1
  await zarusoba()
  order=0
  console.log("三人目")
  order=1
  await temprasoba()
  order=0
}

var order=0
sobaya()

実行結果。

"開店"
"一人目"
"そば計量完了2"
"てんぷら素材準備完了5"
"そばゆで完了7"
"そばあらい完了3"
"てんぷら完了10"
"もりつけ完了5"
"二人目"
"そば計量完了2"
"そばゆで完了7"
"そばあらい完了3"
"もりつけ完了5"
"三人目"
"そば計量完了2"
"てんぷら素材準備完了5"
"そばゆで完了7"
"そばあらい完了3"
"てんぷら完了10"
"もりつけ完了5"
"お店終了90"

以上、Promiseを使った動作サンプルでした。

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?