【问题标题】:Executing 3 asynchronous operations (where the 2nd one depends of a condition)执行 3 个异步操作(第二个取决于条件)
【发布时间】:2013-04-16 19:50:10
【问题描述】:

我正在从事一个 durandal / 微风 项目。

我需要在我的激活函数中执行几件事。感谢promises 我能够链接异步操作。请注意,我仍然是所有这些事情的初学者,所以请不要犹豫,更正我的代码。

我的 viewModel 中有以下激活函数:

var activate = function (routeData) {

    initLookups()

    var idTran = parseInt(routeData.idTran);
    var idItin = parseInt(routeData.idItin);

    return datacontext.getTransportById(idTran, transport)
            .then(function () { return datacontext.getItineraryById(idItin, itinerary); });
}

所以在return语句中:

  1. 感谢getTransportById,我填写了transport observable

  2. 然后感谢getItineraryById,我填写了itinerary observable

-

到目前为止一切顺利。此代码按预期工作并完成工作(可能未优化)。现在我需要在这两个操作之间插入一个条件,以创建一个新实体(如果 idItin==-1)。在这种情况下,将创建一个新实体。我尝试使用下面的代码,但它不起作用:我的意思是 promise 似乎没有在这里完成他的工作,因此无需等待异步操作完成即可显示视图。

var activate = function (routeData) {

    initLookups()

    var idTran = parseInt(routeData.idTran);
    var idItin = parseInt(routeData.idItin);

    return datacontext.getTransportById(idTran, transport)
            .then(function () { if (idItin == -1) return datacontext.createItineraryDetailTransport(idTran); })
            .then(function () { return datacontext.getItineraryById(idItin, itinerary); });
}

下面是datacontext的createItineraryDetailTransport函数:

var createItineraryDetailTransport = function (idTransport) {

    var initialValues = ({
        transportId: idTransport
    });

    var newItinerary = manager.createEntity(entityNames.itinerary, initialValues);
    return manager.addEntity(newItinerary);
}

那么有人知道如何编码这个东西吗?

【问题讨论】:

  • 你确定没有其他事情发生吗?你的代码对我来说似乎是正确的。这个小提琴是否展示了你想要做的事情? jsfiddle.net/bEfrS/1

标签: breeze durandal


【解决方案1】:

我认为正确的方法是:

return datacontext.getTransportById(idTran, transport).then(function () {
    return datacontext.getItineraryById(idItin, itinerary).then(function(){
        if (idItin == -1) return datacontext.createItineraryDetailTransport(idTran);
        //You have to return something different tu null,false,undefined... or a promise
        return true; 
    );
});

另外,如果不需要依次执行此调用,您可以使用 Q 库 (https://github.com/kriskowal/q) 并行执行。解决方案可能是:

if(idItin ==-1){
    //CreateItineraryDetailTransport don't return a promise.
    //You can call that like a normal methond.
    //It is not a asyncronous methond
    datacontext.createItineraryDetailTransport(idTran);
}
return Q.all([datacontext.getTransportById(idTran, transport),datacontext.getItineraryById(idItin, itinerary)]);

-----编辑-----

在其他两个调用之间进行创建的解决方案:

   return datacontext.getTransportById(idTran, transport).then(function () {
        if (idItin == -1) return datacontext.createItineraryDetailTransport(idTran).then(function(){
            return datacontext.getItineraryById(idItin, itinerary);
        });
        return datacontext.getItineraryById(idItin, itinerary)
    });

   // I am using Q to do this method return a promise
    var createItineraryDetailTransport = function (idTransport) {

        var deferred = Q.defer();

        var initialValues = ({
            transportId: idTransport
        });

        var newItinerary = manager.createEntity(entityNames.itinerary, initialValues);
        manager.addEntity(newItinerary);

        deferred.resolve(true);
        return deferred.promise;
    }

你也可以使用 Q.fcall:

return Q.fcall(function(){ datacontext.createItineraryDetailTransport(idTran);};

我认为也许,您不需要 createItineraryDetailTransport 返回一个承诺。也许这个解决方案也是可能的:

return datacontext.getTransportById(idTran, transport).then(function () {
    if (idItin == -1) datacontext.createItineraryDetailTransport(idTran);
    return datacontext.getItineraryById(idItin, itinerary);
});

【讨论】:

  • 感谢您的建议。一个问题:您如何看待 createItineraryDetailTransport 不返回承诺?在这个函数中,return 语句设置在 manager.addEntity 上,我认为这个返回了一个承诺。
  • 您可以在这里查看:breezejs.com/sites/all/apidocs/classes/…。 'addEntity' 方法返回添加的实体而不是承诺。
  • 几乎不错。我需要在另外两个电话(而不是最后一个电话)之间拨打createItineraryDetailTransport。那么如何继续让这个函数返回一个promise呢?
  • 嗯我想到了另一个问题:有时这个函数createItineraryDetailTransport 永远不会被调用,因为条件 (idItin == -1) 是假的。我尝试.then(function () { if (idItin == -1) return datacontext.createItineraryDetailTransport(idTran); else return; }),但它不起作用。在这种情况下,似乎 (idItin==-1) 最后一次调用从未执行。
  • 谢谢你,你帮了我很多。
最近更新 更多