Extjs 如何避免通过多次回调传递承诺来解决承诺灵巧的

Extjs 如何避免通过多次回调传递承诺来解决承诺灵巧的,extjs,asynchronous,rally,promise,deftjs,Extjs,Asynchronous,Rally,Promise,Deftjs,正如我的代码所示,我目前正在向两个异步回调函数(success和callback)传递一个承诺。我认为应该可以用不同的方式来做,但我还没有找到其他方法 下面是我的函数,它创建承诺并等待它们全部完成: _onModelLoaded: function(model) { var promises = []; _.each(this._customRecords, function(defect, index) { promises.push(this._getHis

正如我的代码所示,我目前正在向两个异步回调函数(success和callback)传递一个承诺。我认为应该可以用不同的方式来做,但我还没有找到其他方法

下面是我的函数,它创建承诺并等待它们全部完成:

_onModelLoaded: function(model) {
    var promises = [];

    _.each(this._customRecords, function(defect, index) {
        promises.push(this._getHistory(model, defect));
    }, this);

    Deft.Promise.all(promises).then({
        success: function(something) {
            console.log('woot',something);
        }
    });
},
\u getHistory
函数创建一个承诺,然后将其传递到两个函数中(\u onHistoryLoaded和\u onRevisionsLoaded),以便在运行这些回调后,承诺得到解决:

_getHistory: function(model,defect) {
    var deferred = Ext.create('Deft.promise.Deferred');

    model.load(Rally.util.Ref.getOidFromRef(defect.RevisionHistory), {
        scope: this,
        success: function(record) {
            this._onHistoryLoaded(defect, record, deferred);
        }
    });

    return deferred.promise;
},

_onHistoryLoaded: function(defect, record, def) {
    record.getCollection('Revisions').load({
        fetch: ['RevisionNumber', 'CreationDate', 'User', 'Description'],
        scope: this,
        callback: function(revisions) {
            this._onRevisionsLoaded(revisions, defect, def);
        }
    });
},

_onRevisionsLoaded: function(revisions, defect, def) {

    _.each(revisions, function(revision, revisionIndex) {
        // Do stuff with each revision
    }, this);

    def.resolve(defect);
},
我不一定需要最终缺陷通过承诺,我只是将其放在resolve语句中进行测试

注意:我的代码运行正常,我只是想简化一下


有没有一种方法可以避免只通过几个异步函数来实现承诺?我将尝试提供一些有用的提示,但首先需要注意几个问题

  • 我对你试图解决的领域问题一无所知,这使得你很难确定事物的最佳名称,也很难确定每个功能单元的具体位置

  • 您使用的库似乎不支持Promises/A+和下一版本JavaScript中使用的Promise API。您可以在以下位置阅读关于真正承诺的规范:我在以下位置维护了我最喜欢的实现的简短列表:

  • 我将尝试编写您的代码,就像我用“Promise”编写代码一样,这是这些实现中的第一个,也是我自己编写的

    因为onHistoryLoaded实际上是一个异步操作,所以将其名称更改为它执行的操作,并让它返回一个承诺。对已添加的
    onRevisionsLoaded
    执行相同的操作,并使
    getHistory
    只执行一项作业:

    _onModelLoaded: function(model) {
        var promises = _.map(this._customRecords, function(defect, index) {
            this._getHistoryRevisions(model, defect).then(function (revisions) {
                _.each(revisions, function (revision, revisionIndex) {
                  // Do stuff wich each revision
                }, this);
            }.bind(this));
        }, this);
    
        Promise.all(promises).done(function(something) {
            console.log('woot',something);
        });
    },
    
    _getHistoryRevisions: function (model, defect) {
        return this._getHistory(model, defect).then(function (record) {
            return this._getRevisions(record);
        }.bind(this));
    },
    
    _getHistory: function(model, defect) {
        return new Promise(function (resolve, reject) {
            model.load(Rally.util.Ref.getOidFromRef(defect.RevisionHistory), {
                scope: this,
                success: function(record) {
                    resolve(record);
                }
            });
        }.bind(this));
    },
    
    _getRevisions: function(record) {
        return new Promise(function (resolve, reject) {
            record.getCollection('Revisions').load({
                fetch: ['RevisionNumber', 'CreationDate', 'User', 'Description'],
                scope: this,
                callback: function(revisions) {
                    resolve(revisions);
                }
            });
        }.bind(this));
    }
    

    只要有可能,最好根据函数所做的事情来命名函数,而不是根据引起函数的原因来命名。他们不应该真的需要与他们之前或之后发生的事情联系在一起。承诺背后的很大一部分思想是,它使我们更容易回到编程的同步模型,在这个模型中,我调用一个函数,它做一件事,然后返回一个值。一个函数对其使用位置的了解越少,就越容易在其他地方重复使用:)

    由@ForbesLindesay提供的答案非常有用。但是,我使用的是Deft 0.8.0,因此在实现这些承诺方面存在一些差异。以下是我如何让链条工作的:

    _onModelLoaded: function(model) {
        var promises = [];
    
        _.each(this._customRecords, function(defect, index) {
            promises.push(this._getHistoryRevisions(model, defect).then(function (revisions) {
                // do stuff with revisions
            }.bind(this)));
        }, this);
    
        Deft.Promise.all(promises).then(function(something) {
            console.log('woot',something);
        }.bind(this));
    },
    
    _getHistoryRevisions: function (model, defect) {
        return this._getHistory(model, defect).then(function (record) {
            return this._getRevisions(record);
        }.bind(this));
    },
    
    _getHistory: function (model, defect) {
        var deferred = Ext.create('Deft.promise.Deferred');
    
        model.load(Rally.util.Ref.getOidFromRef(defect.RevisionHistory), {
            scope: this,
            success: function(record) {
                deferred.resolve(record);
            }
        });
    
        return deferred;
    },
    
    // grabbing the revisions for each defect
    _getRevisions: function(record) {
        var deferred = Ext.create('Deft.promise.Deferred');
    
        record.getCollection('Revisions').load({
            fetch: ['RevisionNumber', 'CreationDate', 'User', 'Description'],
            scope: this,
            callback: function(revisions) {
                deferred.resolve(revisions);
            }
        });
    
        return deferred;
    },
    
    主要区别来自最后两个函数,
    \u getHistory
    \u getRevisions
    ——我没有返回
    新承诺(…)
    ,而是使用
    Ext.create('Deft.Promise.deferred')创建了一个延迟对象
    返回并在回调中解析

    希望这能帮助其他人解决使用旧版本DeftJS的问题