我有多个Javascript函数,每个函数都执行一些DOM操作,然后运行ajax请求。我希望能够运行第一个函数,它操纵DOM然后触发它的ajax请求,然后,当ajax请求完成时,我想运行第二个函数,如果ajax请求返回true,或者停止执行其余的的函数和一些其他DOM操作(如显示错误消息)。
我希望这些函数一个接一个地顺序运行,并且只有在它们的ajax请求都没有返回false时才继续运行。如果它们都没有返回false,那么所有它们都应该运行,最后我会在“always”回调中进行一些操作。
我该如何做到这一点?
我的第一个想法是使用promises,以保持代码清洁,但经过几个小时的阅读后,我无法知道如何使这项工作。
下面是我当前的代码,这是我执行时在控制台中获得的代码:
inside test1
inside test2
inside test3
fail
[arguments variable from fail method]
always
[arguments variable from always method]
这是我想要在我的控制台中获取的内容(请注意缺少“inside test3”字符串):
inside test1
inside test2
fail
[arguments variable from fail method]
always
[arguments variable from always method]
以下是代码:
(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)
有什么想法吗?
答案 0 :(得分:1)
我不熟悉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)
答案 1 :(得分:1)
使用promises确实使代码更加清晰
注意:Promise / A + promise .then和.catch回调只接受一个参数,所以不需要查看arguments
,只需使用一个参数
此代码(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
函数的(已解析)结果数组
它创造了一个(已解决的)承诺,以“开始”承诺链
Array#map链接每个函数(this.test1等),然后在之前的结果中执行.then。每个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();
答案 2 :(得分:0)
你不需要使用承诺 - 也许你知道这一点,但你可以继续在prevoius的成功块中调用下一个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)