【发布时间】:2022-01-18 17:00:55
【问题描述】:
我很难解决一些在我的笔记本电脑开发环境中运行良好的功能(即使我使用 NODE_ENV=production 运行它),但是当我将它部署到 Google Cloud Run 时,我会遇到错误,例如
Default
2021-12-15T12:16:35.016406Z at TCP.done (_tls_wrap.js:564:7)
Default
2021-12-15T12:16:35.016414Z(Use `node --trace-warnings ...` to show where the warning was created)
Default
2021-12-15T12:16:35.016426Z(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
Default
2021-12-15T12:16:35.116284Z(node:1) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Default
2021-12-15T12:16:35.116931Z(node:1) UnhandledPromiseRejectionWarning: Error: socket hang up
Default
2021-12-15T12:16:35.116954Z at connResetException (internal/errors.js:639:14)
Default
2021-12-15T12:16:35.116969Z at TLSSocket.socketCloseListener (_http_client.js:449:25)
Default
2021-12-15T12:16:35.116979Z at TLSSocket.emit (events.js:412:35)
Default
2021-12-15T12:16:35.116989Z at net.js:686:12
Default
2021-12-15T12:16:35.116999Z at TCP.done (_tls_wrap.js:564:7)
导致我的脚本停止。在我的本地版本中,它会继续运行而不会停止。这非常令人沮丧,因为我需要一直将代码上传到 Cloud Run 以测试我的代码。我正在盲目测试它,因为错误没有出现在我的开发版本中。
我对 Node.js 还是很陌生,并且经常在使用 .then()、链接 .then()、promise、使用 resolve() 时遇到困难,因此代码很可能是错误的。
我的问题在这里:
- 为什么这个错误只出现在 Cloud Run 上?
- 如何以相同的方式配置我的本地计算机,使其显示相同的警告和错误 - 以便解决此问题?
我的代码(简化):
function createOrUpdateSpotterData(data) {
// NOTE: Data comes from API and not from DB, thus no info such as twitter_status
// TODO: Separate into a create or update, in order to not check twitter ID every time.
return new Promise( async function (resolve) {
var twitterId = await twitterApi.getTwitterIdFromUsername(cleanedUsername)
data['twitter_numeric'] = twitterId
resolve(data)
}).then( (data) => {
db.collection('spotters').doc(data.marker).set(data)
}).catch( (error) => { console.log(error) })
}
async function updateSpottersJsonToDb() {
console.log("> updateSpottersJsonToDb")
return new Promise( (resolve, reject) => {
readStorageData(remote_files['spotters'])
.then( async (spotterListJson) => {
var spotterList = JSON.parse(spotterListJson)
await spotterList.forEach((spotter) => {
createOrUpdateSpotterData(spotter)
})
})
.then(() => {
resolve()
})
.catch((error) => {console.error(error)})
}).catch((error) => {console.error(error)})
【问题讨论】:
-
对于初学者,您可以停止使用将现有 Promise 包装在另一个手动创建的 Promise 中的 Promise 反模式。当你这样做时,在错误处理中很容易出错,这是完全没有必要的。您可以只使用代码已经生成的第一个承诺 - 无需将其包装在新的承诺中。
-
createOrUpdateSpotterData()是异步的吗?仅供参考,await spotterList.forEach(...)中的await什么都不做,因为.forEach()没有返回值并且不知道async。await仅在您等待承诺时才做某事。如果此循环中有异步内容,请将其更改为普通的for循环和await循环内的实际异步操作。 -
另外,你知道
.catch((error) => {console.error(error)})会记录错误然后“吃掉”它,这样调用者就不会看到错误了吗? -
感谢您的 cmets。我知道当我在编码时学习时,我可能会犯很多非常糟糕的错误。然而,我发现很难对 promise、.then 和 await 有一个很好的直觉。 1.你是什么意思,具体来说,承诺反模式。你的意思是在新的 Promise 中有 .then() 吗?
-
2. createOrUpdateSpotterData() 不是异步的。如果是这样,它会改变什么吗?感谢您提供关于 await 和 forEach 的提示,我有这种感觉,但无法确认。