这一个开始在我的皮肤下...
我现在正在玩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));
})
首先,我在注释“ ... this work”下使用两行,它确实起作用;将网址写入Firestore数据库。到目前为止,一切都很好。
然后,我决定变得幻想起来,并决定使用对象工厂来管理以下事实:在一个端口上(通过仿真器)在提供服务的本地主机上使用Express会话,而在另一个端口上使用有角度的前端在会话上造成了一些麻烦管理。简而言之,我设置了一个工厂,该工厂将为我返回一个对象,该对象将在本地运行或在Firebase云托管上使用其他策略进行管理。
这是Promise开始不履行承诺的地方!?
第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)
}
}
}
答案 0 :(得分:0)
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异步,然后等待它和内部异步功能。