First of all rollback is something that I do not care about.
I would like to be able to lock a sequence of async functions/promises/tasks (let's call it a "transaction") with a name/id (or array of names), so that they happen in sequence, and so that any other "transaction" with the same name(s) that are run by another part of the system are delayed from starting until the running transaction using the same name(s) has completed. So it basically is queueing the sequences of async tasks, or "transaction"s.
Here is some example code of the situation:
function a() { // do stuff return new Promise(/*...*/); } function b() { // do stuff return new Promise(/*...*/); } function c() { // do stuff return a.then(() => b()); }
Now at any time the system could call a
, b
, or c
, and when it does I don't want c
and b
running at the same time, but obvious c
depends on b
.
I've been looking for a package on npm to help with this but I haven't found anything, I wonder if anyone can suggest something that I might have missed that would help with this?
6 Answers
Answers 1
I think gulp
tasks can help you out of the box. This guarantees that c
always run after b
and so b
after a
const gulp = require('gulp'); gulp.task('a', done => { // do stuff console.log('a'); done(); }); gulp.task('b', ['a'], done => { // do stuff console.log('b'); done(); }); gulp.task('c', ['b'], done => { // do more stuff console.log('c'); done(); }); gulp.start('c'); // Logs a, b, c
Answers 2
Use async/await and have babel transpile it. Async Babel Docs
function a() { // do stuff return new Promise(/*...*/); } async function b() { const aData = await a(); // do stuff return new Promise(/*...*/); } async function c() { const bData = await b(); // do stuff return bData; }
Answers 3
You can go for https://github.com/Reactive-Extensions/RxJS
They have many functions to handle single/multiple/dependent/parallel async calls.
Answers 4
You could write your own little transaction manager.
const transactions = {}; function doTransaction(name, promiseFunc) { transactions[name] = (transactions[name] || Promise.resolve()).then(promiseFunc); }
Answers 5
function a() { // do stuff return new Promise(/*...*/); } function b() { // do stuff return new Promise(/*...*/); } function c() { // do stuff return new Value; } a().then(function(data_a) { // you can make use of return value (which is data_a) here or as an argument for function b or even function c b().then(function(data_b) { // you can make use of return value (which is data_b) here or as an argument for function c c().then(function(data_c) { // do your coding here }); }); });
you can check this link for reference : https://spring.io/understanding/javascript-promises
Answers 6
Ok, here's my take. You use a wrapper for your function b
which returns and object with 2 methods: doCall
and wait
. The wrapper should be called only once.
doCall
will call your function and trace its completion for the wait() function.
wait()
will wait for the completion and always resolve when doCall() finishes
Now for the code, also on CodePen (see developer console):
function wrapPromiseFn(fn) { var prev = null; var doCall = function() { var retValue; prev = new Promise(function(resolve, reject) { retValue = fn(); retValue.then(function(result) { resolve(true); }); retValue.catch(function(result) { resolve(true); }); }); return retValue; }; var wait = function() { return prev ? prev : Promise.resolve(false); }; return { doCall: doCall, wait: wait }; } function a() { return Promise.resolve(42); } function b() { //return Promise.reject(new Date()); return Promise.resolve(new Date().getTime()); } var wrappedB = wrapPromiseFn(b); function doStuff() { return wrappedB.wait().then(function(didWait) { return a().then(function(_a) { return wrappedB.doCall().then(function(_b) { console.log("didWait, a, b: ", didWait, _a, _b); }); }); }); } //run it twice to prove it did wait doStuff().then(doStuff)
It proves the concept, of course it would need some polish to pass arguments from doCall
to the wrapped function.
0 comments:
Post a Comment