使用async/await仍遇函数溢出:语音识别数据传递异常
问题
尝试在函数间传递嵌套变量时未达预期,async/await未按预期控制执行顺序,导致传递给后续函数的content是对象而非字符串。
尝试的代码
async function processVoicedSearch() { try { console.log("starting getVoicedData"); const a = await getVoicedData(); console.log("getVoicedData finished running"); console.log("starting numberMatcher"); let { matchedData, matchedNumber } = await tscriptNumberMatcher(getVoicedData()); console.log("numberMatcher finished running"); console.log("starting nextMatcher"); const result = await nextMatcher(matchedData, matchedNumber); console.log("nextMatcher finished running"); console.log("starting getResponse"); const markup = await getResponse(nextMatcher(result)); console.log("getResponse finished running"); } catch (err) { console.log(err) } }
日志显示content在tscriptNumberMatcher启动后才返回,导致报错:
starting getVoicedData bundle.js:6923 The value of event.resultIndex is: undefined bundle.js:6924 The type of the event.resultIndex is: undefined bundle.js:6873 getVoicedData finished running bundle.js:6875 starting numberMatcher bundle.js:6923 The value of event.resultIndex is: undefined bundle.js:6924 The type of the event.resultIndex is: undefined bundle.js:6993 tscriptNumberMatcher is running [object Object] undefined bundle.js:6888 TypeError: Cannot read properties of undefined (reading 'match') at tscriptNumberMatcher (bundle.js:6997:26) at processVoicedSearch (bundle.js:6876:48) bundle.js:6923 The value of event.resultIndex is: 0 bundle.js:6924 The type of the event.resultIndex is: number bundle.js:6934 This is the transcript: 10 bananas bundle.js:6946 string
getVoicedData原实现:
//getVoicedData function function getVoicedData() { //creating recognition variable using the speechRecognition constructor var recognition = new speechRecognition() var content = '' recognition.continuous = true if (content.length) { content += '' } recognition.start(); //Display voice recognition is on message, when recognition starts recognition.onstart = function() { instructions.text("Voice Recognition is on") } //When result (voice) is indicated (heard), start processing voice recognition recognition.onresult = function (event) { console.log("The value of event.resultIndex is: " + event.resultIndex); console.log("The type of the event.resultIndex is: " + (typeof event.resultIndex)); do { if (event.resultIndex == undefined) {return} } while (event.resultIndex == undefined); var current = event.resultIndex; var transcript = event.results[current][0].transcript console.log("This is the transcript: " + transcript); content += transcript console.log(typeof content); return content; } return recognition.onresult(content); }
问题原因
getVoicedData不是异步函数:它没有返回Promise,await getVoicedData()不会等待语音识别完成,直接返回recognition.onresult(content)的无效结果——这是一个未正确触发回调时的undefined,且你直接调用了onresult函数,而非等待事件触发。- 重复调用
getVoicedData:在tscriptNumberMatcher(getVoicedData())里再次调用该函数,而非使用第一次await得到的a变量,导致重复启动语音识别,传递的是新识别实例的相关对象,而非预期的content字符串。 onresult回调返回值无效:onresult是事件回调,它的返回值无法被getVoicedData捕获,必须用Promise包裹语音识别流程,在收到有效结果时主动resolve。
解决方案
1. 改造getVoicedData为返回Promise的异步函数
function getVoicedData() { return new Promise((resolve, reject) => { var recognition = new speechRecognition() var content = '' recognition.continuous = true recognition.onstart = function() { instructions.text("Voice Recognition is on") } recognition.onresult = function (event) { console.log("The value of event.resultIndex is: " + event.resultIndex); console.log("The type of the event.resultIndex is: " + (typeof event.resultIndex)); if (event.resultIndex === undefined) { reject(new Error("Invalid result index")); return; } var current = event.resultIndex; var transcript = event.results[current][0].transcript; console.log("This is the transcript: " + transcript); content += transcript; console.log(typeof content); // 若需连续识别,可监听end事件再resolve;这里以收到第一个结果就结束为例 recognition.stop(); resolve(content); } recognition.onerror = function(event) { reject(event.error); } recognition.start(); }); }
2. 修正processVoicedSearch的调用逻辑
async function processVoicedSearch() { try { console.log("starting getVoicedData"); const voicedContent = await getVoicedData(); console.log("getVoicedData finished running, content:", voicedContent); console.log("starting numberMatcher"); // 复用已获取的voicedContent,而非重新调用getVoicedData let { matchedData, matchedNumber } = await tscriptNumberMatcher(voicedContent); console.log("numberMatcher finished running"); console.log("starting nextMatcher"); const result = await nextMatcher(matchedData, matchedNumber); console.log("nextMatcher finished running"); console.log("starting getResponse"); // 直接传递result,而非再次调用nextMatcher(result) const markup = await getResponse(result); console.log("getResponse finished running"); } catch (err) { console.error(err); } }
关键说明
- 用Promise包裹语音识别流程,在
onresult触发并获取有效转录内容时调用resolve传递结果,出错时调用reject捕获错误。 - 避免重复调用
getVoicedData,复用第一次await得到的结果,确保后续函数拿到正确的字符串内容。 getResponse中直接传递已得到的result,无需再次执行nextMatcher。
内容的提问来源于stack exchange,提问作者e-driver1
相关产品推荐
相关产品推荐

