Reputation: 101
Hi i have simple code like that:
jQuery(function ($) {
function Item(val) {
this.val = val
var self = this;
this.generateTrDOM = function () {
var tr = '<tr>';
tr += '<td>' + self.val + '</td>';
tr += '</tr>';
return tr;
};
}
function ItemsCollection() {
this.someHandler = $('#some_table_id');
this.data = [];
var self = this;
this.getData = function () {
return new Promise(function (resolve, reject) {
$.post(base_url + 'controller/action', {
action_type: 'get_items'
}, function (data) {
self.prepareData(data).then(resolve());
}, "json");
});
};
this.prepareData = function (data) {
return new Promise(function (resolve, reject) {
for (var x = 0; x < data.length; x++) {
self.data.push(
new Item(data[x])
);
}
});
};
this.updateTable = function () {
for (var x = 0; x < self.data.length; x++) {
self.someHandler.append(self.data[x].generateTrDOM());
}
};
}
var data = new ItemsCollection();
data.getData() //this is done second
.then(
data.updateTable(); //this is done first - i dont not want to
);
});
I want to data.updateTable() took place after the data.getData() after AJAX request but its start before. I read about the promises and in my other project its worked very well.
Which I did not understand. Thanks for some advices.
Upvotes: 3
Views: 113
Reputation: 17654
try to avoid nested promises to keep your async code linear.
check this post : Are nested promises normal in node.js? ( i know this is not node but it's the same idea :P )
and to do so, you'll need to call getData
, resolve it, then call prepareData
and resolve it , then updateTable
like :
jQuery(function ($) {
function Item(val) {
this.val = val
var self = this;
this.generateTrDOM = function () {
var tr = '<tr>';
tr += '<td>' + self.val + '</td>';
tr += '</tr>';
return tr;
};
}
function ItemsCollection() {
this.someHandler = $('#some_table_id');
this.data = [];
var self = this;
this.getData = function () {
return new Promise(function (resolve, reject) {
$.post(base_url + 'controller/action', {
action_type: 'get_items'
}, function (data) {
resolve(data);
}, "json");
});
};
this.prepareData = function (data) {
return new Promise(function (resolve, reject) {
for (var x = 0; x < data.length; x++) {
self.data.push(
new Item(data[x])
);
}
resolve(self.data);
});
};
this.updateTable = function (data) {
for (var x = 0; x < self.data.length; x++) {
self.someHandler.append(data[x].generateTrDOM());
}
};
}
var data = new ItemsCollection();
data.getData()
.then((result) => {
return data.prepareData(result);
})
.then((prearedData) => {
return data.updateTable(prearedData);
});
});
here's a working fiddle for that https://jsfiddle.net/aejvsxke/5/ ( i replaced your $post
with a $.get
to a fake api and added console.log
in each function for testing purposes, so you can see the order of the execution )
use this to compare the two codes and see the differences : https://www.diffchecker.com/diff
hint : for this.getData
you can return the $.post
directly as it returns a promise itself (no need to wrapp it in a promise and no need for the callback ) as of jQuery 1.5 : https://api.jquery.com/jquery.post/
so it becomes like this :
this.getData = function () {
return $.post(base_url + 'controller/action', {
action_type: 'get_items'
}, "json");
};
i hope this re
solves your problem ;) or at least gives you an idea :P
Upvotes: 1
Reputation: 2058
This should fix the problem. As jfriend00 said, you have to pass a function reference to then(..). If you pass data.updateTable() to then(..) the function is executed immediately.
var data = new ItemsCollection();
data.getData()
.then(data.updateTable);
Upvotes: 2