-
Notifications
You must be signed in to change notification settings - Fork 629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add defer feature of Golang for testing #262
Comments
So defer is simply an helper for : await new Promise(res => {
await RemoveFile(filename);
res();
}); Right? |
@zekth here is the example test(async ({ defer }) => {
console.log("do first job");
defer(async () => {
console.log("1");
});
console.log("do second job");
defer(async () => {
console.log("2");
});
console.log("do third job");
defer(async () => {
console.log("3");
});
console.log("job done.");
});
// print out
// do first job
// do second job
// do third job
// job done.
// 3
// 2
// 1 |
I get it. Using the same defer behaviour LIFO after all the sync code has been executed. |
Maybe call it |
I don’t like the idea because it needs to be called in a special context to work. (Unless I’m missing something?) It’s impossible to implement the general semantics that Go has. |
@ry After the test function is executed (regardless of reject or resolve), then the This is achievable. and it can be Looking back, it can also add hooks like test(async ({ defer, after }) => {
after(async () => {
console.log('do the job after this test finish');
});
}); |
@axetroy But it only works in test, and the name suggests it can work elsewhere... If we could implement this generally, I'd be all for it - but I think that would be impossible without a compilation pass. |
I am not sure about the semantics of Go, but Promises are already scheduled out of turn in JavaScript as a microtask. So all this would be is a function that would reschedule at the end of the current queue before the next macrotask. That should be implementable just in the runtime by creating a new Promise. |
In Go, the deferred function is executed before the function returns to caller, but after the body of the function is executed. I haven't really thought thru how to implement this, but it seems not possible... If @axetroy has a way to do this in general, I'd be all for adding it. (It's super useful and a very nice feature.) But if it's restricted to |
One way, if there is a compelling use case, would be that the test(function testSomething({ defer }) {
defer(() => console.log("b"));
console.log("a");
}); Anything throwing in there would be attributed to the test function. No magic, just "standard" JavaScript. |
After I finish this #261, I will do a PR. |
@ry I have implemented this feature. try it out save as deno defer.ts type DeferFunc = () => Promise<void>;
type Defer = (fn: DeferFunc) => void;
interface Context {
defer: Defer;
}
type func<T> = (context: Context) => Promise<T>;
function deferify<T>(fn: func<T>) {
return async function(): Promise<T> {
const defers: DeferFunc[] = [];
const context: Context = {
defer(fn) {
defers.push(fn);
return;
},
};
async function dequeue() {
while (defers.length) {
const deferFn = defers.pop();
if (deferFn) {
try {
await deferFn();
} catch {}
}
}
}
return fn(context)
.then((r: any) => {
return dequeue().then(() => r);
})
.catch((err: Error) => {
return dequeue().then(() => Promise.reject(err));
});
};
}
deferify(async ({ defer }) => {
console.log('do first job');
defer(async () => {
console.log('1');
});
console.log('do second job');
defer(async () => {
console.log('2');
});
console.log('do third job');
defer(async () => {
console.log('3');
});
console.log('job done.');
})();
// do first job
// do second job
// do third job
// job done.
// 3
// 2
// 1 If you think this is ok, can you reopen the issue? |
@axetroy Sorry - it's a bit too non-standard and boilerplate-y for me. Please submit it to https://github.com/denoland/registry |
defer
in Golang is easy is useful especially in the test.eg.
do the same thing in
Deno
I wrote a library before. https://github.com/axetroy/godefer
The text was updated successfully, but these errors were encountered: