28

我试图了解 JavaScript(特别是 AngularJS)中的承诺。

我在服务中有一个函数,我们称之为它fooService,它检查我们是否加载了一些数据。如果有,我只希望它返回,如果没有,我们需要加载数据并返回一个承诺:

this.update = function(data_loaded) {
    if (data_loaded) return;  // We've loaded the data, no need to update

    var promise = Restangular.all('someBase').customGet('foo/bar').then(function(data) {
        // Do something with the data here
    }

    return promise;
}

我有另一个函数,然后调用如下update函数fooService

fooService.update(data_loaded).then(function() {
    // Do something here when update is finished
})

我的问题是,如果我们不需要在update函数中加载数据,则不会返回承诺,因此.then()不会在我的其他函数中调用。这里应该采用什么方法-基本上,update()如果我们不需要从 Restangular 调用中获取数据,我想立即从函数中返回已解决的承诺?

4

5 回答 5

50

由于您的 Promise 使用与 JavaScript 本机相同的语法,因此您可以使用并返回一个已解析的 JavaScript Promise:Promise.resolve()

return(Promise.resolve("MyReturnValue"));
于 2015-07-09T08:56:00.243 回答
27

当前接受的答案过于复杂,并且滥用了延迟反模式。这是一个更简单的方法:

this.update = function(data_loaded) {
    if (data_loaded) return $q.when(data);  // We've loaded the data, no need to update

    return Restangular.all('someBase').customGet('foo/bar')
                             .then(function(data) {
        // Do something with the data here 
    });
};

或者,更进一步:

this._updatep = null;
this.update = function(data_loaded) { // cached
    this._updatep = this._updatep || Restangular.all('someBase') // process in
                                                .customGet('foo/bar'); //.then(..
    return this._updatep;
};
于 2014-07-17T05:07:24.200 回答
6

AngularJS 的$q服务将在这里为您提供帮助。它很像Kris Kowal 的 Q Promise 库。

当您有一个可能返回承诺或值的异步方法时,请使用$q.when方法。它将接受传递给它的任何内容,无论是一个承诺还是一个值,并创建一个承诺,该承诺将根据传递的承诺被解析/拒绝,或者如果传递了一个值则被解析。

$q.when( fooService.update(data_loaded) ).then(function(data){
   //data will either be the data returned or the data
   //passed through from the promise
})

然后在你的更新函数中返回数据而不是仅仅返回

if (data_loaded) return data_loaded;
于 2014-07-17T03:39:35.943 回答
0

Elo 的 answer类似,您可以使用 async/await 语法返回已解决的承诺:

this.update = async (data_loaded) => {

    if (data_loaded) 
        return await null;  // Instead of null, you could also return something else
                            // like a string "Resolved" or an object { status: 200 }
    else 
        return await OtherPromise();
}
于 2018-07-23T11:27:45.723 回答
-2

你可以这样使用$q.defer()

this.update = function (data_loaded) {
    var deferred = $q.defer();

    if (data_loaded) {
        deferred.resolve(null); // put something that your callback will know the data is loaded or just put your loaded data here.
    } else {
        Restangular.all('someBase').customGet('foo/bar').then(function(data) {
            // Do something here when update is finished
            deferred.resolve(data);
        }
    }

    return deferred.promise;
};

希望这可以帮助。

于 2014-07-17T03:37:49.627 回答