承诺不解析在快速中间件中的异步函数中



这个开始深入我的皮肤...

我现在正在使用Firebase和Functions,并制作了一个非常简单的API,并将express作为中间件。

所以我有这条路线:

...
app.get('/getAuthUrl', async (req, res) => {
const s: sessionManagement.ISessionManagement = 
sessionManagement.SessionFactory.createSession(
functions.config().aproxy.session.mode, req, db)
// ...this work
const getback = req.query.getback;
await db.collection('tokens').doc('getback').set({getback});
// this not?!
s.setReturnURL(req.query.getback);
res.setHeader('Cache-Control', 'private');
res.status(200).json(new Message(redirectUri));
})

首先,我在注释"...这项工作",它确实奏效了;将 URL 写入 Firestore 数据库。目前为止,一切都好。

然后我决定花哨起来,决定使用对象工厂来管理这样一个事实,即在一个端口上使用本地主机上的快速会话(使用模拟器(和另一个端口上的角前端在会话管理方面引起了一些头痛。长话短说,我设置了一个工厂,它将返回一个对象,该对象将管理我是否在本地运行或在Firebase云托管上使用不同的策略。

这就是承诺开始不持有他们的地方......承诺!?

在我的工厂内s.setReturnURL(..调用此方法的行:

export interface ISessionManagement {
setReturnURL: (value: string) => void
}
export class FirestoreSession implements ISessionManagement {
private database: FirebaseFirestore.Firestore
private fingerprint: string
constructor(database: FirebaseFirestore.Firestore, fingerprint: string) {
this.database = database
this.fingerprint = fingerprint
}
setReturnURL(value: string) {
console.log('setReturnURL')
this.writeDoc(value, 'getback')
}
writeDoc(value: string, document: string) {
(async () => {
console.log('inside async')
const doc = this.database.collection('tokens').doc(document).set({value})
const result = await doc
console.log(result)
})().catch(error => {
console.log(error)
})
console.log('finish writeDoc')
}
}
export class SessionFactory {
public static createSession(mode: string, req: express.Request, db: FirebaseFirestore.Firestore) : ISessionManagement {
if (mode === 'fingerprint' ) {
console.log('fingerprint mode');
// Use for local testing, since in multiport solution, cookie will not be unique to a session
return new FirestoreSession(db, fingerPrintMe(req));
} else {
// For production
return new ExpressSession(req);
}
}
}

所以,这里是控制台输出的执行流,如果使用我的工厂对象:

✔  functions[app]: http function initialized (http://localhost:5000/myplayground/us-central1/app).
i  functions: Beginning execution of "app"
>  fingerprint mode
>  setReturnURL
>  inside async
>  finish writeDoc
i  functions: Finished "app" in ~1s

上面的代码是我完成这项工作的最新尝试。我尝试了很多变化,移动我的异步/等待,但没有任何让步!

我错过了什么???我觉得答案会让我爬到一些岩石下,但我不在乎,我需要把这个从我的脑海中移开:-(

更新

事实证明,我需要一直异步/等待到返回承诺以使这项工作的调用,而且,您不能等待返回 void 的函数,所以我不得不更改接口签名。所以这里的代码片段是有效的:

app.get('/getAuthUrl', async (req, res) => {
... 
await s.setReturnURL(req.query.getback)
...
})
...
export interface ISessionManagement {
setReturnURL: (value: string) => any 
}
export class FirestoreSession implements ISessionManagement {
...
async setReturnURL(value: string) {
await this.writeDoc(value, 'getback')
}
...
async writeDoc(value: string, document: string) {
try {
const doc = await this.database.collection('tokens').doc(document).set({value})
console.log(doc)
} catch (error) {
console.log(error)            
}
}
}
const doc = this.database.collection('tokens').doc(document).set({value})
const result = await doc

为什么不干脆const result = await this.database.collection('tokens').doc(document).set({value})

`writeDoc(value: string, document: string) {
(async () => {
console.log('inside async')
const doc = this.database.collection('tokens').doc(document).set({value})
const result = await doc
console.log(result)
})().catch(error => {
console.log(error)
})
console.log('finish writeDoc')
}`

首先,writedoc不是一个承诺,也没有等待。内部异步函数也不会被等待,因此一旦执行暂停,函数的其余部分就会继续。因此,它将执行,其余的内部异步函数将排队等待下一个事件循环。 然后一切都返回并退出。

使 writedoc 异步,并等待它和内部异步函数。

最新更新