1
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?

js 非同期関数の書き方

Last updated at Posted at 2025-01-03

適当な関数

sync.js
function fx() {
    
    const a = 100 * 300;
    console.log('時間です');
  
    const ret = 'abc';
    
    let aa = [];
    for (let i = 0; i < 100; i++) {
      aa.push(i);
    }
  
    console.log(ret);
  
    const ret2 = 1000;
    
    const a2 = 'abc';
    let x = a2 + 'xyz';
    console.log(ret, ret2);

    
}

fx();
fx();

結果は

時間です
abc
abc 1000
時間です
abc
abc 1000

同期的に動いている。

async.js
async function fx() {
    await Promise.resolve();  //ここで非同期

    const a = 100 * 300;
    console.log('時間です');
  
    await Promise.resolve(); //ここで非同期

    const ret = 'abc';
    let aa = [];
    for (let i = 0; i < 100; i++) {
      aa.push(i);
    }
  
    console.log(ret);
  
    await Promise.resolve(); //ここで非同期

    const ret2 = 1000;
    const a2 = 'abc';
    let x = a2 + 'xyz';
    console.log(ret, ret2);

    
}

fx();
fx();

functionの前にasyncをいれ、ブレークするところにawait Promise.resolve();をいれる。

結果は

時間です
時間です
abc
abc
abc 1000
abc 1000

非同期になった。
ブレークしたところで、処理が切り替わる。

ちなみに

async.js
function delay() {
    return new Promise(resolve => setTimeout(resolve, 0));
  }


async function fx() {
    await delay();  //ここで非同期

    const a = 100 * 300;
    console.log('時間です');
  
    await delay(); //ここで非同期

    const ret = 'abc';
    let aa = [];
    for (let i = 0; i < 100; i++) {
      aa.push(i);
    }
  
    console.log(ret);
  
    await delay(); //ここで非同期

    const ret2 = 1000;
    const a2 = 'abc';
    let x = a2 + 'xyz';
    console.log(ret, ret2);

    
}

fx();
fx();

このようにsetTimeoutをPromiseにくるんで渡してもよい。

delay.js
function delay() {
  return new Promise(resolve => setImmediate(resolve));
}

setImmdiateでもOK

Promise.resolveとsetImmediateの違い

Promise.resolve()Microtask Queueにタスクを追加する
setImmediate()Task Queueにタスクを追加する

このため、Promise.resolve()の方が優先的に実行される

非同期関数から返り値を戻す場合

async.js
async function fx() {
    await Promise.resolve();  //ここで非同期

    return '終わったよ'

}
    
    
fx().then(ret => {
    console.log(ret);
});

retuenで返して、thenで受け取る。
fx()Promiseを返すから。

async.js
async function fx() {
    await Promise.resolve();  //ここで非同期

    return '終わったよ'

}
    

(async () => {
    const ret = await fx(); 
    console.log(ret);
})();

asyncで書き換えてもOK。

長いループを非同期にする場合

loop.js
async function processAll() {
  const totalIterations = 510;
  const batchSize = 100;

  
  for (let i = 0; i < totalIterations; i += batchSize) {
      const start = i;
      const end = Math.min(i + batchSize, totalIterations); // 最後のバッチが100回未満の場合に対応

      await (async() => {
          console.log(`処理中: ${start}`);

          for (let i = start; i < end; i++) {
          
              // ここで実際の処理を行う(例: API 呼び出し、データ処理など)
          
          }
          await Promise.resolve();

      })();

      
  }

  console.log('すべての処理が完了しました');
}

processAll();
processAll();

100回ループするごとにブレークして非同期にループする。

処理中: 0
処理中: 0
処理中: 100
処理中: 100
処理中: 200
処理中: 200
処理中: 300
処理中: 300
処理中: 400
処理中: 400
処理中: 500
処理中: 500
すべての処理が完了しました
すべての処理が完了しました

内部のループを関数にしてもいい

loop.js
async function processBatch(start, end) {
    console.log(`処理中: ${start}`);

    for (let i = start; i < end; i++) {
      
      // ここで実際の処理を行う(例: API 呼び出し、データ処理など)
      
    }
    await Promise.resolve();
}
  

async function processAll() {
    const totalIterations = 510;
    const batchSize = 100;

    
    for (let i = 0; i < totalIterations; i += batchSize) {
        const start = i;
        const end = Math.min(i + batchSize, totalIterations); // 最後のバッチが100回未満の場合に対応

        await processBatch(start, end);


    }
  
    console.log('すべての処理が完了しました');
}
  
processAll();
processAll();

以上

1
0
0

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
1
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?