Google Actions调用随机维基API始终返回相同响应问题排查
错误原因
代码的执行时序完全写错了,这是固定返回同一词条的核心原因:
- 你把调用维基随机词条接口的
request请求写在了意图处理逻辑的外层,还把app.handle意图注册代码塞在了request的回调里。
Firebase云函数的运行机制是:只有实例冷启动(首次部署、长时间无请求后新启动实例)时才会执行函数顶层的全局代码,同一实例后续接收的所有请求,都只会运行对应触发的处理逻辑,不会重复跑顶层代码。
这就导致:函数冷启动时只会发起1次API请求,拿到某一次返回的固定词条内容,之后才注册
wiki_random的处理回调,回调里引用的body永远是冷启动那次拿到的固定数据。后续所有用户触发意图时,根本不会重新发起API请求,自然每次返回的内容都一模一样。
你在本地Node控制台每次运行都是全新启动进程,每次都会重新执行请求拿新数据,所以本地测试不会复现这个问题。
另外原代码还有三个隐藏问题:
- 所有变量都未加
const/let声明,会污染全局作用域 - 异步请求没有告知函数等待执行完成,容易出现响应超时、内容为空的问题
- 在异步回调里注册意图处理逻辑,存在时序风险,可能请求进来的时候处理逻辑还没注册完成,直接报错。
修正方案
把API请求移到意图处理回调内部,每次用户触发意图时才发起新的请求拿随机词条,修正后的Index.js代码如下:
const { conversation } = require('@assistant/conversation'); const functions = require('firebase-functions'); const request = require('request'); const app = conversation(); const WIKI_RANDOM_URL = 'https://en.wikipedia.org/api/rest_v1/page/random/summary'; app.handle('wiki_random', conv => { // 返回Promise让云函数等待异步请求完成后再返回响应 return new Promise((resolve, reject) => { request(WIKI_RANDOM_URL, (error, response, body) => { if (error || response.statusCode !== 200) { conv.add('获取随机词条失败,请稍后重试。'); return resolve(); } const dataObj = JSON.parse(body); const speech = `${dataObj.title}... ${dataObj.extract}`; conv.add(speech); resolve(); }); }); }); exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
Package.json不需要改动,额外提示:你目前依赖的request库已经停止维护,后续可以替换为axios、node-fetch等仍在维护的HTTP请求库。
内容的提问来源于stack exchange,提问作者BJ Dunc
相关产品推荐
相关产品推荐

