Open rumkin opened 9 years ago
What advantage does defer
give you over simply doing this?
co(function*() {
// code
}).catch(err => {
db.close();
});
If we can get the same functionality with the existing API, adding a syntactically pretty method like defer
might add additional unnecessary complexity. Please let me know if I am misunderstanding the defer
method.
Defer make generator function atomic. It could be passed with variable, it share closed scope and thus it is standalone independent method. If I could do so with usual promise behaviour it will look like this:
function example() {
var db;
return co(function *(){
db = yield DB.connect();
// do the job ...
}).then(function(){
db.close();
}).catch(function(){
db.close();
});
};
As you see we have three separated code blocks which shares same responsibility. But if I wish more complex behaviour It would became into mess of promises.
What you're looking for is finally
@felixfbecker finally
or .finally()
?
choose one:
co-style
co(function *() {
const db = yield DB.connect();
try {
yield db.query(...); // do the job, might throw in case of error
} finally {
db.close(); // but always close db, no matter if error or not
}
});
Promise-style
DB.connect()
.then(db =>
db.query(...)
.then(() => db.anotherQuery(...))
.finally(() => {
db.close();
})
})
(Promise have a problem when you need to access something of the scope in a previous then handler, like the db. So you can either assign db to a variable db
out of the scope like you did or nest your promise handlers like my example)
@rumkin Can you explain why should co.defer
be yield-able. Doesn't co.defer
be enough without yield
@IdpugantiSanjay to properly associate deferred code with the currently executing function. And if the function has several block of code which should be executed in a finally statement it could affect performance significantly due to nested try/catch blocks.
What's about golang-like deferred calls with co? I think it should looks like that:
In this way db connection will be closed in any way after throwing or returning. Yielding of methods wrapped in defer should return control immediately and put deferred call into deferred stack.