1

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

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

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

_getHistory函数创建一个 Promise,然后将其传递给两个函数(_onHistoryLoaded 和 _onRevisionsLoaded),以便一旦运行这些回调,promise 就会得到解决:

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

我不一定需要通过promise传递最终的缺陷,我只是把它放在resolve语句中进行测试。

注意:我的代码运行正常,我只是在寻找简化。

有没有办法避免创建一个承诺,只通过几个异步函数来解决它?

4

2 回答 2

2

我将尝试提供一些有用的提示,但首先要注意几点。

  1. 我对您要解决的领域问题一无所知,这使得很难确定事物的最佳名称或每个功能单元在什么地方适合事物的宏伟计划。

  2. 您使用的库似乎不支持 Promise/A+ 和下一版本的 JavaScript 中使用的 Promise API。您可以在http://promisesaplus.com/阅读真正的 Promise 规范,我在http://www.promisejs.org/implementations/维护了我最喜欢的实现的简短列表

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

由于 onHistoryLoaded 实际上是一个异步操作,因此将其名称更改为它执行的操作并让它返回一个承诺。做同样的事情onRevisionsLoadedgetHistory只做一项工作:

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

在可能的情况下,最好根据它们所做的事情来命名函数,而不是根据它们的原因来命名。它们不应该真的需要与它们之前或之后发生的事情相耦合。Promise 背后的大部分想法是,它可以更容易地回到我调用函数的同步编程模型,它会做一件事,然后返回一个值。一个函数对它在哪里使用的意识越少,它就越容易在其他地方重用:)

于 2013-12-25T00:07:04.033 回答
0

@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;
},

主要区别来自最后两个函数,_getHistory并且-我必须创建一个延迟对象,_getRevisions而不是返回 a ,以便在回调中返回和解析。new Promise(...)Ext.create('Deft.promise.Deferred');

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

于 2014-04-09T18:23:18.133 回答