lin*_*ram 2 javascript mongoose mongodb node.js async-await
嘿,
我正在尝试从猫鼬withTransaction回调中传递数据。现在,我正在使用以下实现回调的代码:
const transactionSession = await mongoose.startSession()
await transactionSession.withTransaction(async (tSession) => {
try {
// MARK Transaction writes & reads removed for brevity
console.log("Successfully performed transaction!")
cb(null, "Any test data")
return Promise.resolve()
} catch (error) {
console.log("Transaction aborted due to error:", error)
cb(error)
return Promise.reject()
}
})
} catch (error) {
console.log(error)
return cb(error)
}
Run Code Online (Sandbox Code Playgroud)
withTransaction可以在此处找到正在使用的帮助程序的更详细片段。
withTransaction可以在此处找到有关帮助程序的官方 Mongoose 文档的链接。
目前,我正在使用回调从回调中传递数据withTransaction:
cb(null, "Any test data")
然而,问题是自然而然地在Promise.resolve()返回之前首先执行回调。这意味着(在我的情况下)在提交任何必要的数据库写入之前将成功响应发送回客户端:
// this is executed first - the callback will send back a response to the client
cb(null, "Any test data")
// only now, after the response already got sent to the client, the transaction is committed.
return Promise.resolve()
Run Code Online (Sandbox Code Playgroud)
为什么我认为这是一个问题:
老实说,我不确定。如果当时没有任何数据库写入,则向客户端发送成功响应是不正确的。有人知道处理这个特定用例的适当方法吗?
我想过withTransaction使用这样的东西从助手传递数据:
const transactionResult = await transactionSession.withTransaction({...})
Run Code Online (Sandbox Code Playgroud)
我试过了,响应是CommandResultMongoDB 的,它不包括我在已解决的承诺中包含的任何数据。
如果在提交事务之前将成功响应发送回客户端,这是一个问题吗?如果是这样,从withTransaction助手传递数据从而在发回响应之前提交事务的适当方法是什么?
我会很感激我得到的任何建议。
关于如何在几个层面上正确使用 Promises,这里似乎存在一些混淆。
如果函数应该接受回调,则不要返回 Promise。如果函数应该返回一个 Promise,请使用 Promise 提供的回调:
const transactionSession = await mongoose.startSession()
await transactionSession.withTransaction( (tSession) => {
return new Promise( (resolve, reject) => {
//using Node-style callback
doSomethingAsync( (err, testData) => {
if(err) {
reject(err);
} else {
resolve(testData); //this is the equivalent of cb(null, "Any test data")
}
});
})
Run Code Online (Sandbox Code Playgroud)
让我们更详细地看一下:
return new Promise( (resolve, reject) => {这将创建一个新的 Promise,并且 Promise 为您提供了两个回调以供使用。resolve是表示成功的回调。您将要返回的对象传递给它。请注意,我已经删除了async关键字(稍后会详细介绍)。
例如:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
Run Code Online (Sandbox Code Playgroud)
(err, testData) => {此函数用于将 Node 样式映射cb(err, result)到 Promise 的回调。
Try/catch 只能用于同步语句。让我们比较一下同步调用、Node 风格(即cb(err, result))异步回调、Promise 和使用 await:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
Run Code Online (Sandbox Code Playgroud)
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
Run Code Online (Sandbox Code Playgroud)
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
Run Code Online (Sandbox Code Playgroud)
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Run Code Online (Sandbox Code Playgroud)
Promise.resolve()Promise.resolve()创建一个新的 Promise 并使用未定义的值解析该 Promise。这是以下的简写:
new Promise( (resolve, reject) => resolve(undefined) );
Run Code Online (Sandbox Code Playgroud)
与此等效的回调将是:
cb(err, undefined);
Run Code Online (Sandbox Code Playgroud)
asyncasync与await. 如果await在函数中使用,则该函数必须声明为async.
就像await将 Promise 展开(resolve变成一个值,然后reject变成一个异常)一样,async 将代码包装到一个 Promise 中。一个return value语句被翻译成Promise.resolve(value),并抛出的异常throw e被翻译成Promise.reject(e)。
考虑以下代码
async () => {
return doSomethingSync();
}
Run Code Online (Sandbox Code Playgroud)
上面的代码等价于:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Run Code Online (Sandbox Code Playgroud)
如果你在没有 的情况下调用上述任何一个函数await,你将得到一个 Promise。如果您选择await其中任何一个,您将被返回一个值,或者将抛出异常。
| 归档时间: |
|
| 查看次数: |
1867 次 |
| 最近记录: |