q承诺在完成之前解决了?

时间:2015-05-07 15:28:16

标签: angularjs q

我想我可能会遗漏一些关于承诺如何运作的基本原则,因为我似乎从来没有得到我期望的结果,所以希望有人能够纠正我的想法。

在这种情况下,这是一个相对容易的电话。我有一个角度工厂,其中包括从API获取一些数据(调用mongodb)。 由于存在$ http请求(这是异步的),我将http调用包装在$ q函数中,如果成功则返回resolve,如果错误则返回reject

factory.loadLayout = function (layoutName) {
    return $q(function(resolve, reject){
        $http.get('/api/getlayout/'+layoutName)
            .success(function (data) {
                layout = data;
                console.log("Got " + layout.name);
                resolve('OK');
            })
            .error(function(data,status,headers,config){
               reject(new Error( status));
            });


    });
}

然后我有另一个函数依赖于第一个函数中收集的数据,称为getButtonId,但据我所知,即使它包含在.then中,它似乎是在承诺得到解决之前召集。

var promise = padArea.loadLayout(layoutName);
    promise.then(padArea.getButtonId('A0'));

那么我错过了什么?

==更新== 所以使用q.defer

尝试相同的事情
factory.loadLayout = function (layoutName) {
    var defer = $q.defer()
        $http.get('/api/getlayout/'+layoutName)
            .success(function (data) {
                layout = data;
                console.log("Got " + layout.name);
                defer.resolve('OK');
            })
            .error(function(data,status,headers,config){
               defer.reject(new Error( status));
            });
    return defer.promise;
}

仍然没有按照我的预期工作,并且在http完成之前仍然会调用.then中的函数。

==更新2 == 好吧,所以让它工作(如果我只是在.then内的工厂中调用该函数,它直接调用它,但是,如果我将它包装在下面的函数中,它突然起作用。任何人都可以解释为什么虽然,因为对我而言,将调用包装到函数内部似乎与调用函数没有任何区别。

padArea.loadLayout(layoutName).then(function(result){
    padArea.getButtonId('A0')
});

奇怪的是,只要我将第二个调用(.then中的一个)包装起来,我的原始代码就可以了。

2 个答案:

答案 0 :(得分:3)

只需使用$http承诺:

factory.loadLayout = function (layoutName) {
  return $http.get('/api/getlayout/'+layoutName)
        .success(function (data) {
            layout = data;
            console.log("Got " + layout.name);
            resolve('OK');
        })
        .error(function(data,status,headers,config){
           reject(new Error( status));
        });
}

然后使用它......

factory.loadLayout(param).then(function (response) { ... });

我明白你要做什么。而是创建一个来自$q

的定义
factory.loadLayout = function (layoutName) {
  var defer = $q.defer();
    $http.get('/api/getlayout/'+layoutName)
        .success(function (data) {
            layout = data;
            console.log("Got " + layout.name);
            defer.resolve('OK');
        })
        .error(function(data,status,headers,config){
           defer.reject(new Error( status));
        });
  return defer.promise;
}

答案 1 :(得分:2)

你也可以使用$ q.defer():

deferred = $q.defer();

$http.get('/api/getlayout/'+layoutName)
    .success(function (data) {
        layout = data;
        deferred.resolve("OK");
    })
    .error(function (data,status,headers,config){
        deferred.reject(new Error(status));
    })

return deferred.promise;

如果您不只是执行http请求,并且可以控制返回,这可能会更加通用。