2017-05-13 56 views
4

首先回滾是我不關心的事情。javascript中的異步交易

我想能夠鎖定一系列異步函數/承諾/任務(讓我們稱之爲「事務」)與名稱/ ID(或名稱數組),以便它們按順序發生,因此係統其他部分運行的具有相同名稱的任何其他「事務」將從啓動延遲到使用相同名稱的正在運行的事務已完成。所以它基本上是排隊的異步任務,或「交易」的序列。

這裏的情況的一些示例代碼:

function a() 
{ 
    // do stuff 
    return new Promise(/*...*/); 
} 


function b() 
{ 
    // do stuff 
    return new Promise(/*...*/); 
} 



function c() 
{ 
    // do stuff 
    return a.then(() => b()); 
} 
隨時

目前,該系統可以調用ab,或c,當它我不想cb運行在同時,但明顯的c取決於b

我一直在尋找在NPM包,以幫助這一點,但我沒有發現任何東西,我不知道是否有人可以建議的東西,我可能會錯過這將有幫助呢?

+1

我真的不知道問題是什麼。如果你調用'c()。然後(...)',這是不是你想要的?另外,我認爲'c()'的主體應該是'return a()。then(()=> b())',而不是'return a.then(()=> b())' –

+0

爲什麼不使用共享作用域變量作爲標誌來知道是否已經有B或C函數正在執行? – Kulvar

+0

如果有調用函數的條件,聽起來像你需要的是一個委託人。由於b返回一個承諾,我猜你想要的是給b的一個調用等到c不再被處理。然後你會讓調用者在調用b之前等待一個標誌。 – Dacheng

回答

3

你可以去https://github.com/Reactive-Extensions/RxJS

他們有許多函數來處理單/多/依賴/並行異步調用。

+0

嗯我不理解RxJS如何處理我的問題後簡單看文檔,也許你可以爲我提供更多的見解?也許是一個代碼示例? – erikvold

3

你可以寫你自己的小事務管理器。

const transactions = {}; 

function doTransaction(name, promiseFunc) { 
    transactions[name] = (transactions[name] || Promise.resolve()).then(promiseFunc); 
} 
+0

雖然我有一個組成交易的承諾鏈,但不只是一個承諾。 – erikvold

+0

我添加了一個我正在描述的問題的代碼示例。 – erikvold

+0

我不明白。 'doTransaction'可以被調用任意次數,同一個名字的promise會按照我想要的順序執行。 –

8

我認爲gulp任務可以幫助你開箱。這保證了c總是b後運行等ba

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 

Try it!

2
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 
    }); 
    }); 
}); 

您可以檢查此鏈接以供參考:https://spring.io/understanding/javascript-promises

4

使用異步/等待,並有通天transpile它。 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; 
} 
1

好的,這是我的要求。 您可以使用函數b的包裝函數返回對象,並使用兩種方法:doCallwait。包裝只能被調用一次。

doCall將調用你的函數並跟蹤其完成的wait()的函數。

wait()將等待完成,並始終解決在doCall()完成

現在的代碼,也CodePen(見開發者控制檯):

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)

它證明了這個概念,當然它需要一些波蘭語將參數doCall傳遞給包裝函數。

+0

確保'b'在任何給定時間不會運行多次的另一用法(即concurrency = 1):'wrappedB.wait()。then(wrappedB.doCall())' –