问题
I have a button which when clicked opens a modal(dashboard_name) in which user enters some value. Based on the value after he clicks submit on that modal I call another function which opens another modal and user enters a different value there and finally when he clicks submit on this modal, I call an api to verify everything is correct.
Now, the problem is when I click on the first button to open the modal the execution doesn't wait for the function to get the data from the dashboard_name modal and then the graph_name modal. Instead it directly jumps to the api function call, which is right coz that's how jQuery works. But I wanted to know how to use deferred and promise to make this execution serial.
Function for the first button when clicked.
$('#add_to_dash').click(function(e){
dashboard_submit();
graph_submit();
});
this function gets the dashboard modal and tries to get the value.
function dashboard_submit(){
//do something
}
this function after success of the dashboard_submit function tries to get value for the graph modal
function graph_submit(){
//do something
}
and then on form submit i call this following func
<form name="form2" onsubmit="return isDashboardCorrect(dashboard_name);" method="post" action="{{ url_for('dashboards_new') }}">
the function
function isDashboardCorrect(dashboard_name) {
var flag=0;
$.ajax({
async: false,
type: 'GET',
url: 'xyz.com/dashboard/'+dashboard_name,
success: function(data) {
//alert(data);
//do something
});
}
I want all of this to be sequential which is not happening right now i.e. when i click on the first button it doesn`t wait for the functions to execute and directly the isdashboardcorrect() function gets called.
I want the order to be 1. button click 2. dashboard_submit() 3. graph_submit() 4. isdashboardcorrect() serially.
I tried something simpler like
$('#add_to_dash').click(function(e){
alert('addtodashstart');
dashboard_submit().done(function(){
alert('done');
});
alert('addtodashend');
});
function dashboard_submit()
{
alert('dashboardsubmot');
var dfd = new $.Deferred();
$("#d_name_modal_div").modal({backdrop: false}).modal("show");
$('#d_name_modal_submit').on('click', function(){
dashboard_name=$('#dashboard_name').val();
alert(dashboard_name);
if(dashboard_name==null || dashboard_name.trim()=='')
{
alert('Dashboard name is mandatory.');
return false;
}
else
{
dfd.resolve();
return dfd.promise();
}
});
}
When I click the button I call the dashboard_submit function. But here too it doesn`t wait for
`$('#d_name_modal_submit').on('click', function(){
this to execute in the above function and directly hits the api function. What Am i doing wrong?`
Example fiddle : http://jsfiddle.net/LKP66/18/
回答1:
About your second question: You don't get it att all what I've explain it to you, do you?
done()
subscription callbacks are called when you resolve your defferred instance dfd
. It is called almost the very moment you resolve it.
So you are going to open your next dialog when you have recieved the data.
Just take 1-2 hours and try to understand the concept and what I've explained to you. That is very poor programming you are doing there.
http://jsfiddle.net/qoytmgcj/2/
function dashboard_submit() {
alert('Dashboard submit');
var dfd = new $.Deferred();
dashboard_name = 'ram';
$("#d_name_modal_div").modal({
backdrop: false
});
dfd.done(function(){
var dn = $('#dashboard_name');
dn.val('booooooo I recived the data now I can open the dialog');
dn.text(dn.val());
$("#d_name_modal_div").modal("show");
});
dfd.resolve();
return dfd;
}
function wtf() {
var dfd = $.Deferred();
$('#d_name_modal_submit').on('click', function () {
dashboard_name = $('#dashboard_name').val();
alert(dashboard_name);
if ( !$.trim(dashboard_name) ) {
alert('Dashboard name is mandatory.');
return false;
} else {
dfd.resolve();
alert('success');
return dfd;
}
});
}
$('#add_to_dash').click(function (e) {
alert('Add to dash start');
dashboard_submit().done(function () {
wtf();
});
alert('Add to dash end');
});
回答2:
$('#add_to_dash').click(function(e) {
$.when(dashboard_submit()).then(function(){
graph_submit();
});
});
function dashboard_submit() {
var dfd = new $.Deferred();
$.ajax({
....,
....,
success: function (....) {
dfd.resolve();
/*some code...*/
}
});
return dfd.promise();
}
dfd
is an object that can have a few outcomes same as $.ajax()
which also returns deferred, actually. What are ajax outcome? success
, error
, complete
.... and you have callbacks on them. Same thing with an instance of $.Deferred
. However you have a control over what and when the outcome is resolve, reject,....etc. base on your code. As you can see I have receive successfully the data and I call that it was resolved successfully dfd.resolve();
. So you can consider .then()
and .done()
equivalent to success both called on resolve. The difference is that then()
is a method of dfd.promise().then()
while done()
is a method of dfd itself dfd.done()
Ex.2
$('#add_to_dash').click(function(e) {
dashboard_submit().done(function(){
graph_submit();
});
/* That is
dfd.done(function(){
graph_submit();
});
since dashboard_submit() returns dfd
*/
});
function dashboard_submit() {
var dfd = new $.Deferred();
$.ajax({
....,
....,
success: function (....) {
dfd.resolve();
/*some code...*/
}
});
return dfd;
}
Ex.3
As I mentioned $.ajax()
returns $.Deferred
instance so no need to create explicitly one so actually dfd
isn't needed you are provided by one already so:
$('#add_to_dash').click(function(e) {
dashboard_submit().done(function(){
graph_submit();
});
});
function dashboard_submit() {
return $.ajax({
....,
....,
success: function (....) {
/* The dfd that ajax returns is resolved on success by jQuery so no explicit instance creation is needed nor resolving*/
}
});
}
来源:https://stackoverflow.com/questions/29134292/how-to-make-the-calling-function-wait-until-the-called-function-finishes-executi