异步执行2个操作

时间:2013-05-03 14:46:22

标签: knockout.js breeze durandal

我使用Durandal / Breeze / Knockout开发了一个应用程序。

在我的javascript中,我想一个接一个地执行2个异步操作。

  • 第一个收集我所有的'闹钟',其中transportId通过参数传递,类别为'全球'

  • 第二个是删除上面收集的所有这些实体

这是我到目前为止所做的事情:

var checkAlarmsOnTransport = function (id) {

    var alarms = ko.observableArray();
    getAlarms(alarms, id, 'Global')
        .then(deleteAlarms(alarms));
};

var getAlarms = function (alarmsObservable, transportId, category, forceRemote) {
    // Input: transportId
    // Input: category
    // Input: forceRemote: boolean to force the fetch from server
    // Output: alarmsObservable: an observable filled with all the alarms

    if (forceRemote)
        queryCacheAlarms = {};

    var p1 = new Predicate('transportId', '==', transportId);
    var p2 = new Predicate('category', '==', category);
    var query = entityQuery.from('Alarms')
                           .orderBy('id')
                           .where(p1.and(p2));

    var isInCache = (queryCacheAlarms === true);

    if (isInCache && !forceRemote) {
        query = query.using(breeze.FetchStrategy.FromLocalCache);
    } else {
        queryCacheAlarms = true;
        query = query.using(breeze.FetchStrategy.FromServer);
    }

    //old return manager.executeQuery(query)
    //old    .then(querySucceeded)
    //old    .fail(queryFailed);

    var p = manager.executeQuery(query);
    p.then(querySucceeded);
    p.fail(queryFailed);
    return p;

    function querySucceeded(data) {
        console.log("the get return:" + data.results.length); // <---------- added
        alarmsObservable(data.results);
    }
};

var deleteAlarms = function (alarmsObservable) {
    // Input: alarmsObservable: an observable filled with a list of alarms to delete
    // Output: none
    console.log("deleted:" + alarmsObservable().length); // <------------- added
    for (var i = alarmsObservable().length - 1; i >= 0 ; i--) {
        alarmsObservable()[i].entityAspect.setDeleted();
    };
};

我成功地独立测试了这两个功能。现在我想异步使用它,它不起作用。

有什么想法吗?

感谢任何人指出我正确的方向。


更新

我像CodeThug一样更新了我的代码,然后在我的2个函数中添加了2个console.log行来跟踪已完成的操作。见上文。

控制台显示:

  • 删除:0

  • get return:6

所以似乎deleteAlarms函数在getAlarms之前被调用,因此deleteAlarms收到了0个元素的输入。

知道为什么电话会被撤销?

2 个答案:

答案 0 :(得分:1)

getAlarms方法返回如下:

return manager.executeQuery(query)
    .then(querySucceeded)
    .fail(queryFailed);

你打电话给getAlarms就像这样:

getAlarms(alarms, id, 'Global')
    .then(deleteAlarms(alarms));

所以你有效地尝试这样做:

manager.executeQuery(query)
    .then(querySucceeded)
    .fail(queryFailed)
    .then(deleteAlarms(alarms));

但是,您无法在.then()之后链接.fail().then().fail()是可以在promise上调用的方法。 .then()返回一个承诺,你可以用这种方式链接:

myPromise.then(...).then(...).then(...)

您可以在.fail()之后获得.then(),因为.then()会返回一个承诺:

myPromise.then(...).fail(...);

但是,.fail()返回undefined,并且您无法在未定义时调用.then()。所以这不会起作用

// This won't work (this is what you're trying to do)
myPromise.then(...).fail(...).then(...);

请改为尝试:

var p = manager.executeQuery(query);
p.then(querySucceeded);
p.fail(queryFailed);
return p;

然后您可以将呼叫保持原样{<1}}:

getAlarms

答案 1 :(得分:0)

我认为问题可以出现在这一部分:

var alarms = ko.observableArray();
getAlarms(alarms, id, 'Global')
  .then(deleteAlarms(alarms));

你必须这样做:

var alarms = ko.observableArray();
getAlarms(alarms, id, 'Global')
  .then(function(){deleteAlarms(alarms);});

因为您需要将函数传递给当时。

我希望这会对你有所帮助。