Javascript 如何按顺序运行多个函数,并在其中任何一个函数失败时停止所有函数?
我有多个Javascript函数,每个函数都执行一些DOM操作,然后运行一个ajax请求。我希望能够运行第一个函数,该函数操作DOM,然后触发其ajax请求,然后,当ajax请求完成时,如果ajax请求返回true,我希望运行第二个函数,或者停止其余函数的执行,并执行其他一些DOM操作(例如显示错误消息) 我希望这些函数按顺序一个接一个地运行,并且只有当它们都没有从ajax请求返回false时才能继续运行。如果它们都没有返回false,那么它们都应该运行,最终我将在“始终”回调中执行一些操作 我怎样才能做到这一点 我的第一个想法是使用承诺,保持代码更干净,但在阅读了几个小时后,我就是不知道如何让它工作 下面是我当前的代码,这是我在控制台中执行时得到的代码:Javascript 如何按顺序运行多个函数,并在其中任何一个函数失败时停止所有函数?,javascript,jquery,promise,deferred,sequential,Javascript,Jquery,Promise,Deferred,Sequential,我有多个Javascript函数,每个函数都执行一些DOM操作,然后运行一个ajax请求。我希望能够运行第一个函数,该函数操作DOM,然后触发其ajax请求,然后,当ajax请求完成时,如果ajax请求返回true,我希望运行第二个函数,或者停止其余函数的执行,并执行其他一些DOM操作(例如显示错误消息) 我希望这些函数按顺序一个接一个地运行,并且只有当它们都没有从ajax请求返回false时才能继续运行。如果它们都没有返回false,那么它们都应该运行,最终我将在“始终”回调中执行一些操作 我
inside test1
inside test2
inside test3
fail
[arguments variable from fail method]
always
[arguments variable from always method]
这就是我希望在控制台中获得的内容(请注意缺少的“inside test3”字符串):
代码如下:
(function($) {
var tasks = {
init: function() {
$.when(
this.test1(),
this.test2(),
this.test3()
).done(function() {
console.log('done');
console.log(arguments);
})
.fail(function() {
console.log('fail');
console.log(arguments);
})
.always(function() {
console.log('always');
console.log(arguments);
});
},
test1: function() {
console.log('inside test1');
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
},
test2: function() {
console.log('inside test2');
// note the misspelled "typ" arg to make it fail and stop execution of test3()
return $.getJSON('https://baconipsum.com/api/?typ=meat-and-filler');
},
test3: function() {
console.log('inside test3');
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
}
};
tasks.init();
})(jQuery)
有什么想法吗?您不需要使用承诺-也许您知道这一点,但您可以继续在prevoius one的成功块中调用下一个ajax请求,如下所示:
(function($) {
var tasks = {
init: function() {
$.post(url_1, data_1, function(data,status){
if(status == 'success')
{
$.post(url_2, data_2, function(data,status){
if(status == 'success')
{
// ... and the next Ajax request goes here, etc.
}
else {
// show error message if 2nd Ajax request fails
}
}
else {
// show error message if 1st Ajax request failes
}
});
});
}
tasks.init();
})(jQuery)
您不需要使用承诺——也许您知道这一点,但您可以在prevoius one的成功块中继续调用下一个ajax请求,如下所示:
(function($) {
var tasks = {
init: function() {
$.post(url_1, data_1, function(data,status){
if(status == 'success')
{
$.post(url_2, data_2, function(data,status){
if(status == 'success')
{
// ... and the next Ajax request goes here, etc.
}
else {
// show error message if 2nd Ajax request fails
}
}
else {
// show error message if 1st Ajax request failes
}
});
});
}
tasks.init();
})(jQuery)
我不太熟悉jquery的承诺 但这应该行得通
(function ($) {
var tasks = {
init: function () {
this.test1().done(this.test2).done(this.test3)
.done(function () {
console.log('done');
console.log(arguments);
})
.fail(function () {
console.log('fail');
console.log(arguments);
})
.always(function () {
console.log('always');
console.log(arguments);
});
},
test1: function () {
console.log('inside test1');
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
},
test2: function () {
console.log('inside test2');
// note the misspelled "typ" arg to make it fail and stop execution of test3()
return $.getJSON('https://baconipsum.com/api/?typ=meat-and-filler');
},
test3: function () {
console.log('inside test3');
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
}
};
tasks.init();
})(jQuery)
我不太熟悉jquery的承诺 但这应该行得通
(function ($) {
var tasks = {
init: function () {
this.test1().done(this.test2).done(this.test3)
.done(function () {
console.log('done');
console.log(arguments);
})
.fail(function () {
console.log('fail');
console.log(arguments);
})
.always(function () {
console.log('always');
console.log(arguments);
});
},
test1: function () {
console.log('inside test1');
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
},
test2: function () {
console.log('inside test2');
// note the misspelled "typ" arg to make it fail and stop execution of test3()
return $.getJSON('https://baconipsum.com/api/?typ=meat-and-filler');
},
test3: function () {
console.log('inside test3');
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
}
};
tasks.init();
})(jQuery)
使用承诺确实会使代码更干净 注意:Promise/A+Promise.then和.catch回调只接受一个参数,因此不需要查看
参数
,只需使用一个参数即可
此代码(ES2015+)显示了如何简单
let p = Promise.resolve();
Promise.all([this.test1, this.test2, this.test3].map(fn => p = p.then(fn()))).then(allResults =>
或者,使用array.reduce
[this.fn1, this.fn2, this.fn3].reduce((promise, fn) => promise.then(results => fn().then(result => results.concat(result))), Promise.resolve([])).then(allResults =>
在这两种情况下,allResults
都是来自testN
函数的(已解析)结果数组
它创建了一个(已解决的)承诺来“启动”承诺链
数组#映射将每个要在中执行的函数(this.test1等)链接到上一个结果。每个this.testn
promise的结果都返回到一个新数组中,该数组是promise.all的参数
如果任何一个testN失败,下一个将不会执行
var tasks = {
init () {
let p = Promise.resolve();
Promise.all([this.test1, this.test2, this.test3].map(fn => p = p.then(fn())))
.then(results => {
console.log('done');
console.log(results);
return results; // pass results to next .then
}).catch(reason => {
console.log('fail');
console.log(reason);
return reason; // because I return rather than throw (or return a Promise.reject),
//the next .then can will get `reason` in it's argument
}).then(result => {
console.log('always');
console.log(result);
});
},
test1() {
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
},
test2() {
return $.getJSON('https://baconipsum.com/api/?typ=meat-and-filler');
},
test3() {
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler').then(result => {
if(someCondition) {
throw new Error("sum ting wong");
// or
return Promise.reject(new Error("sum ting wong"));
}
return result;
});
}
};
tasks.init();
对于问题中的代码,您可以进一步简化它
var tasks = {
init () {
let p = Promise.resolve();
const urls = [
'https://baconipsum.com/api/?type=meat-and-filler',
'https://baconipsum.com/api/?typ=meat-and-filler',
'https://baconipsum.com/api/?type=meat-and-filler'
];
Promise.all(urls.map(url => p = p.then(() => $.getJSON(url))))
.then(results => {
console.log('done');
console.log(results);
return results; // pass results to next .then
}).catch(reason => {
console.log('fail');
console.log(reason);
return reason; // because I return rather than throw (or return a Promise.reject),
//the next .then can will get `reason` in it's argument
}).then(result => {
console.log('always');
console.log(result);
});
}
};
tasks.init();
使用承诺确实会使代码更干净
注意:Promise/A+Promise.then和.catch回调只接受一个参数,因此不需要查看参数
,只需使用一个参数即可
此代码(ES2015+)显示了如何简单
let p = Promise.resolve();
Promise.all([this.test1, this.test2, this.test3].map(fn => p = p.then(fn()))).then(allResults =>
或者,使用array.reduce
[this.fn1, this.fn2, this.fn3].reduce((promise, fn) => promise.then(results => fn().then(result => results.concat(result))), Promise.resolve([])).then(allResults =>
在这两种情况下,allResults
都是来自testN
函数的(已解析)结果数组
它创建了一个(已解决的)承诺来“启动”承诺链
数组#映射将每个要在中执行的函数(this.test1等)链接到上一个结果。每个this.testn
promise的结果都返回到一个新数组中,该数组是promise.all的参数
如果任何一个testN失败,下一个将不会执行
var tasks = {
init () {
let p = Promise.resolve();
Promise.all([this.test1, this.test2, this.test3].map(fn => p = p.then(fn())))
.then(results => {
console.log('done');
console.log(results);
return results; // pass results to next .then
}).catch(reason => {
console.log('fail');
console.log(reason);
return reason; // because I return rather than throw (or return a Promise.reject),
//the next .then can will get `reason` in it's argument
}).then(result => {
console.log('always');
console.log(result);
});
},
test1() {
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler');
},
test2() {
return $.getJSON('https://baconipsum.com/api/?typ=meat-and-filler');
},
test3() {
return $.getJSON('https://baconipsum.com/api/?type=meat-and-filler').then(result => {
if(someCondition) {
throw new Error("sum ting wong");
// or
return Promise.reject(new Error("sum ting wong"));
}
return result;
});
}
};
tasks.init();
对于问题中的代码,您可以进一步简化它
var tasks = {
init () {
let p = Promise.resolve();
const urls = [
'https://baconipsum.com/api/?type=meat-and-filler',
'https://baconipsum.com/api/?typ=meat-and-filler',
'https://baconipsum.com/api/?type=meat-and-filler'
];
Promise.all(urls.map(url => p = p.then(() => $.getJSON(url))))
.then(results => {
console.log('done');
console.log(results);
return results; // pass results to next .then
}).catch(reason => {
console.log('fail');
console.log(reason);
return reason; // because I return rather than throw (or return a Promise.reject),
//the next .then can will get `reason` in it's argument
}).then(result => {
console.log('always');
console.log(result);
});
}
};
tasks.init();
欢迎来到末日金字塔或回调地狱-想象一下,即使只有10个URL:实际上,问题中的代码比我实际拥有的要短,真正的代码大约有8个ajax请求,还有可能添加更多欢迎加入末日金字塔或回调地狱-想象一下,即使只有10个URL:实际上,问题中的代码比我实际拥有的要短,真正的代码大约有8个ajax请求,可以添加更多感谢,我想它可以工作,如果我不认为有可能添加更多的ajax请求,我会使用它,因此我希望代码易于扩展。。这个解决方案会变得有点混乱与其他几个回调我不知道你到底是什么意思,这链的3个承诺,你创造在一起,这是你问的。我假设在您的实际代码中,除了查找json数据之外,您在函数test1、test2、test3中还做了更多的工作。您还希望进行哪些其他更改?我的意思是,它可以正常工作(或者至少应该可以正常工作),但我希望能够轻松添加更多函数,链接test1、test2、…,test20可能看起来有点混乱,更难维护(如果我想注释掉其中一些呢?),这是一个很好的解决方案,但是这段代码将来可能会被其他开发人员维护,如果我不在的话,我想让他们尽可能地轻松。谢谢,我想它可以工作,如果我不认为有可能添加更多ajax请求,我会使用这段代码,所以我希望代码能够轻松扩展。。这个解决方案会变得有点混乱与其他几个回调我不知道你到底是什么意思,这链的3个承诺,你创造在一起,这是你问的。我假设在您的实际代码中,除了查找json数据之外,您在函数test1、test2、test3中还做了更多的工作。您还希望进行哪些其他更改?我的意思是,它可以正常工作(或者至少应该可以正常工作),但我希望能够轻松添加更多函数,链接test1、test2、…,test20可能看起来有点混乱,更难维护(如果我想注释掉其中一些呢?),这是一个很好的解决方案,但是这段代码将来可能会被其他开发人员维护,如果我不在的话,我想让他们尽可能容易地维护这段代码。这看起来就像我在追求的一样。。。虽然我不确定胖箭头函数是否像普通匿名函数一样得到支持?我会试试看,但这看起来真的很棒!谢谢,@Jaromanda X=>
使代码更加简洁,并且减少了对这是什么的麻烦:p你