如果我只有同步功能并且:
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;
}
但是当函数是异步的时候,我最初会:
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;
});
}
});
添加第三个更加痛苦和耗时。我错过了一个更聪明的方法吗?
答案 0 :(得分:1)
我更喜欢承诺模式。
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个函数,它就会更好地扩展,看起来比嵌套更好。
这假设你想按顺序执行一个接一个的功能。如果您不关心执行顺序,但只是想确保所有异步调用都已完成,那么我会看一下 $ .deferred 模式(jQuery)。这样可以确保如果你有N个异步函数,并且希望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();
从http://eng.wealthfront.com/2012/12/04/jquerydeferred-is-most-important-client/
复制无耻#2我在UI初始化中使用#2nd方式,当几个列表框,下拉列表和任何异步初始化时,并且确保在所有asyncs完成后启用用户界面。为什么不同步你问?为了更好地利用浏览器可以使用的多个http请求。它更快。
答案 1 :(得分:0)
如果您的功能返回承诺,并且您定位的环境支持async / await,那么代码几乎不需要更改:
var err = await f1(a);
if (err)
xxxx
else {
yyyy;
var err2 = await f2(b);
if (err2)
...
else
rrr;
}