【问题标题】:Running one async function inside another [duplicate]在另一个[重复]中运行一个异步函数
【发布时间】:2021-08-22 11:17:04
【问题描述】:

我第一次尝试在 NodeJS 中做一些异步操作时有点卡住了。我阅读了一些关于 Promises 和 async/await 的内容,但仍然对在一个异步函数位于另一个异步函数内部的情况下最好的做法感到困惑。

function startTheater(sourceAudioFile) {
  decodeSoundFile(sourceAudioFile).then((result) => {
    setLight(); //this has to run only run after decodeSoundFile is complete
  });
}

function decodeSoundFile(soundfile) {
  return new Promise(function(resolve, reject) {
    fs.readFile(soundfile, function(err, buf) {
      if (err) throw err
      context.decodeAudioData(buf, function(audioBuffer) {
      playSound();
        findPeaks(pcmdata, samplerate); <<<<<< this function itself has has to finish before decodeSoundFile returns <<<<<<
     if (lightPlant.length != 0) {
        resolve("light plan populated");
      } else {
        reject(new Error("broke promise. unable to populate"));
      }
      }, function(err) {
        throw err
      })
    })
  });
}

以下函数需要一段时间才能完成,但上面的decodeSoundFile 在完成之前返回。当decodeSoundFile 本身就是一个承诺时,我该如何防止这种情况发生?

function findPeaks(pcmdata, samplerate) {
  var interval = 0.5 * 1000;
  var step = samplerate * (interval / 1000);

  //loop through sound in time with sample rate
  var samplesound = setInterval(function() {
    if (index >= pcmdata.length) {
      clearInterval(samplesound);
      console.log("finished sampling sound"); <<this is where decodeSoundFile is good to return after findPeaks execution. 
    }

    for (var i = index; i < index + step; i++) {
      max = pcmdata[i] > max ? pcmdata[i].toFixed(1) : max;
    }
    prevmax = max;
    max = 0;
    index += step;
  }, interval, pcmdata);
}

我如何以正确的方式执行此链接?

【问题讨论】:

  • 这里有一些关于您发布的代码的奇怪之处。在 decodeSoundFile: 1. 什么是audioBuffer - 你永远不会使用它。 2. 什么是lightPlantpcmdatasamplerate——它们不知从何而来。 - 在 findPeaks 中: 1. pevmax 是什么 - 它无处不在
  • 抱歉,我只是想简短地回答我正在处理的所有音频复杂问题。这就是那些孤立变量的来源。
  • 不用放,只是觉得奇怪:p只要知道是什么,不影响答案

标签: javascript node.js promise


【解决方案1】:
import { readFile } from 'fs/promises';

function startTheater(sourceAudioFile) {
    decodeSoundFile(sourceAudioFile).then((result) => {
        setLight(); //this has to run only run after decodeSoundFile is complete
    });
}

function decodeSoundFile(soundfile) {
    return fs.readFile(soundfile)
    .then(buf => new Promise((resolve, reject) => context.decodeAudioData(buf, resolve, reject)))
    .then(audioBuffer => {
        playSound();
        return findPeaks(pcmdata, samplerate);
    })
    .then(() => {
        if (lightPlant.length != 0) {
            return "light plan populated";
        } else {
            return Promise.reject(new Error("broke promise. unable to populate"));
        }        
    });
}

function findPeaks(pcmdata, samplerate) {
    return new Promise(function (resolve, reject) {
        var interval = 0.5 * 1000;
        var step = samplerate * (interval / 1000);

        //loop through sound in time with sample rate
        var samplesound = setInterval(function () {
            if (index >= pcmdata.length) {
                clearInterval(samplesound);
                console.log("finished sampling sound");
                resolve();
            }
            for (var i = index; i < index + step; i++) {
                max = pcmdata[i] > max ? pcmdata[i].toFixed(1) : max;
            }
            prevmax = max;
            max = 0;
            index += step;
        }, interval, pcmdata);
    });
}

根据要求(和 startTheater)在 decodeSoundFile 中使用 async/await

async function startTheater(sourceAudioFile) {
    const result = await decodeSoundFile(sourceAudioFile);
    setLight();
}

async function decodeSoundFile(soundfile) {
    const buf = await fs.readFile(soundfile);
    const audioBuffer = await new Promise((resolve, reject) => context.decodeAudioData(buf, resolve, reject));
    await findPeaks(pcmdata, samplerate);
    if (lightPlant.length != 0) {
        return "light plan populated";
    } else {
        return throw new Error("broke promise. unable to populate");
    }        
}

【讨论】:

  • 刚刚编辑了我的问题,展示了我如何解决decodeSoundFile() 中的承诺。如果是这种情况,当findPeaks promise 嵌套在 decodeSoundFile 中时,findPeaks 仍然可以解决吗?出于某种原因(在阅读了另一篇文章后),我认为只有第一个 resolve 会在一个 promise 嵌套在另一个时起作用
  • 这就是链式承诺的工作方式@user2607717
  • 您可以将您的编辑更改为带有await 的编辑吗?在链接和获得我想要的东西方面,这对我有用。我只是犹豫在承诺中使用承诺,认为可能有更优雅/更聪明的方式,但我想我只是想多了。感谢您的帮助
  • 你为什么需要 await - 我删除了 async/await 因为你没有使用它,不知道你是否知道 - 但是好的
  • @user2607717 - 添加了decodeSoundFile的异步/等待版本
猜你喜欢
  • 2011-06-25
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 1970-01-01
  • 2019-05-22
相关资源
最近更新 更多