有更好的asynchronous编码模式吗?

如果我只有同步function和:

var err = f1(); if (err) xxxx else yyyy; 

我需要添加另一个函数调用,这是依赖于第一个已经成功完成,我可以附加它:

 var err = f1(a); if (err) xxxx else { yyyy; var err2 = f2(b); if (err2) ... else rrr; } 

但是,当function是asynchronous的,我会最初有:

 f1(a, function(err) { if (err) xxxx else yyy; }); 

添加第二个电话将需要一些手术,大量的括号和括号来追踪:

 f1(a, function(err) { if (err) xxxx else { yyy; f2(b, function(err) { if (err) ... else rrr; }); } }); 

增加三分之一更加痛苦和耗时。 我是否更聪明地错过了?

我更喜欢承诺模式。

 var firstMethod = function() { var promise = new Promise(function(resolve, reject){ setTimeout(function() { console.log('first method completed'); resolve({data: '123'}); }, 2000); }); return promise; }; var secondMethod = function(someStuff) { var promise = new Promise(function(resolve, reject){ setTimeout(function() { console.log('second method completed'); resolve({newData: someStuff.data + ' some more data'}); }, 2000); }); return promise; }; var thirdMethod = function(someStuff) { var promise = new Promise(function(resolve, reject){ setTimeout(function() { console.log('third method completed'); resolve({result: someStuff.newData}); }, 3000); }); return promise; }; firstMethod() .then(secondMethod) .then(thirdMethod); 

(无耻复制: https : //html5hive.org/how-to-chain-javascript-promises/ )

一旦你打了5-6个function,它就会比嵌套更好,看上去更好。

这假设你想要按顺序执行一个函数 。 如果你不关心执行的顺序,但只是想确保所有的asynchronous调用已经完成,我会看看$ .deferred模式(jQuery)。 这确保了如果你有N个asynchronous函数,并且你希望N + 1函数在完成之后执行,那么你就有了一个干净的方法来完成它。

例:

 var name = $.post('/echo/json/', {json:JSON.stringify({'name':"Matt Baker"})}); var lastUpdate = $.post('/echo/json/', {json:JSON.stringify({'lastUpdate':"Hello World"})}); $.when(name, lastUpdate) .done(function (nameResponse, lastUpdateResponse) { var name = nameResponse[0].name; var lastUpdate = lastUpdateResponse[0].lastUpdate; $("#render-me").html(name+"'s last update was: "+lastUpdate); }) .fail(function () { $("#error").html("an error occured").show(); 

无耻复制#2: http : //eng.wealthfront.com/2012/12/04/jquerydeferred-is-most-important-client/

例如,在UI初始化中,我使用#第二种方法,当多个列表框,下拉列表和任何asynchronous初始化,并希望确保所有asynchronous完成后启用用户界面。 为什么不同步你问? 为了更好地利用浏览器可以使用的多个http请求。 速度更快

如果你的函数返回promise,并且你的目标环境支持async / await,那么代码几乎不需要改变:

 var err = await f1(a); if (err) xxxx else { yyyy; var err2 = await f2(b); if (err2) ... else rrr; }