承诺错过了解

时间:2018-03-22 22:01:08

标签: javascript ajax asynchronous promise

嗨,我有这样简单的代码:

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
        );
});

我希望 data.updateTable()发生在AJAX请求之后的 data.getData()之后,但是之前的启动。我读到了关于承诺的内容,而在我的其他项目中,它的效果非常好。

我不明白。谢谢你的一些建议。

2 个答案:

答案 0 :(得分:2)

这应该可以解决问题。正如jfriend00所说,你必须将函数引用传递给then(..)。如果将data.updateTable()传递给then(..),则立即执行该函数。

var data = new ItemsCollection();
data.getData()
  .then(data.updateTable);

答案 1 :(得分:1)

尽量避免使用嵌套的promises来保持异步代码的线性。

查看这篇文章:Are nested promises normal in node.js?(我知道这不是节点,但它的想法是相同的:P)

要执行此操作,您需要致电getData,解决问题,然后致电prepareData并解决,然后updateTable如下:

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); 
        });
});

这是https://jsfiddle.net/aejvsxke/5/的工作小提琴(我将$post替换为$.get  假冒api并在每个函数中添加console.log用于测试目的,因此您可以看到执行的顺序)

使用它来比较两个代码并查看差异:https://www.diffchecker.com/diff

提示:对于this.getData,你可以直接返回$.post,因为它返回一个promise本身(不需要在promise中包装它,也不需要回调)从 jQuery 1.5开始https://api.jquery.com/jquery.post/

所以它变成了这样:

this.getData = function () {
    return $.post(base_url + 'controller/action', {
                action_type: 'get_items'        
            }, "json"); 
};

我希望re解决你的问题;或者至少给你一个想法:P