我使用 websockets 与 API Gateway 和 dynamoDB 来维护所有连接 ID。
我想做的是,当收到新消息时,会将消息发送到所有连接的客户端。
例如,在
$default
路由内,将从客户端接收消息。 然后我查询 dynamo 以获取所有连接的 id 并发送该消息。
查询发电机:
const params = {
TableName: process.env.CONNECTIONS_TABLE,
IndexName: process.env.CONNECTIONS_COMPANY_INDEX,
KeyConditionExpression: "company = :company",
ExpressionAttributeValues: {
":company": data.company,
},
};
const response = await dynamodb.query(params).promise();
response.Items.forEach(async (item) => {
try {
await apig
.postToConnection({
ConnectionId: item.connectionId,
Data: JSON.stringify(data),
})
.promise();
} catch (e) {
if (e.statusCode === 410) {
console.log(e)
}
}
});
我遇到的问题是,只有在第二次尝试后,客户端才会收到它。 因此,客户端发送一条消息“123”(上面的代码已成功运行,并且我已验证它获取了所有连接,没有错误),但客户端没有收到任何内容。 客户端发送另一条消息 - “456”,现在两个客户端都会收到“123”消息。
有什么想法为什么会发生这种情况吗?我希望发送的每条消息都会收到发送给所有连接的客户端的相同消息,不会延迟并且总是落后一个。
谢谢!
我面临着完全相同的问题。然后我只需从 API 网关
Remove integration response
离开函数 return {}
在HTTP协议中,发送请求和响应 同步地;沟通本质上是单向的。在 WebSocket 中 协议,通信是双向的。响应是异步的并且是 客户收到的订单不一定与订单相同 客户的消息已发送。另外,后台还可以发送 给客户的消息。
那个
forEach
循环运行得非常快,并启动每个 postToConnection()
调用,有点“在后台”。
一旦
forEach
循环完成并到达 lambda 执行结束,它将终止 lambda 和任何正在运行的后台任务(即挂起的 postToConnection()
调用)。
您需要等待所有的承诺,并带有
await Promise.all(
。
您可以通过在
console.log
调用之前和之后放置 postToConnection
来调试此问题。您将看到第一个日志运行,但第二个日志不会显示,因为 lambda 在运行之前就终止了。
您看到它在第二次运行时起作用的原因是 AWS 认为您的 lambda 正在获得一些持续的流量,因此它会让 lambda 运行更长时间以准备接受更多连接。当 lambda 保持空闲状态以等待连接时,它有机会在被杀死之前完成后台异步任务。