AngularJs:在内部调用$http或$resource时,让方法同步返回
AngularJs: Have method return synchronously when it calls $http or $resource internally
有没有一种方法可以等待promise,这样您就可以从中获得实际结果并返回,而不是返回promise本身?我在想一些类似于C#await关键字如何处理Tasks的东西。
下面是一个例子,说明为什么我希望有一个像canAccess()这样的方法,它返回true或false,而不是promise,这样它就可以在if语句中使用。方法canAccess()将使用$http或$resource进行AJAX调用,然后以某种方式等待promise得到解决。
看起来像这样:
$scope.canAccess = function(page) {
var resource = $resource('/api/access/:page');
var result = resource.get({page: page});
// how to await this and not return the promise but the real value
return result.canAccess;
}
有办法这样做吗?
总的来说,这是个坏主意。让我告诉你为什么。浏览器中的JavaScript基本上是一个单线程的野兽。仔细想想,它在Node.js中也是单线程的。因此,任何在开始等待远程请求成功或失败时不"返回"的操作都可能涉及某种循环,从而延迟请求后代码的执行。类似这样的东西:
var semaphore = false;
var superImportantInfo = null;
// Make a remote request.
$http.get('some wonderful URL for a service').then(function (results) {
superImportantInfo = results;
semaphore = true;
});
while (!semaphore) {
// We're just waiting.
}
// Code we're trying to avoid running until we know the results of the URL call.
console.log('The thing I want for lunch is... " + superImportantInfo);
但是,如果你在浏览器中尝试,但调用需要很长时间,浏览器会认为你的JavaScript代码陷入了循环,并在用户面前弹出一条消息,让用户有机会停止你的代码。因此JavaScript的结构是这样的:
// Make a remote request.
$http.get('some wonderful URL for a service').then(function (results) {
// Code we're trying to avoid running until we know the results of the URL call.
console.log('The thing I want for lunch is... " + results);
});
// Continue on with other code which does not need the super important info or
// simply end our JavaScript altogether. The code inside the callback will be
// executed later.
其思想是,每当服务调用返回时,回调中的代码都将由事件触发。因为JavaScript喜欢事件驱动。JavaScript中的计时器是事件,用户操作是事件,发送和接收数据的HTTP/HTTPS调用也会生成事件。您需要构建代码,以便在事件发生时对其作出响应。
你能不能在远程服务调用返回之前,不把你的代码构造成它认为canAccess是假的,它可能会发现它真的是真的?我在AngularJS代码中一直这样做,我不知道我应该向用户显示的最终权限集是什么,因为我还没有收到它们,或者我一开始还没有收到要在页面中显示的所有数据。我有默认值,直到真实数据返回,然后页面根据新数据调整为新形式。AngularJS的双向绑定使这变得非常容易。
使用.get()回调函数来确保获得已解析的资源。
有用的链接:
- 官方文件
- 如何在AngularJS中添加$resource方法的回调
你不能-angular、Q(promise)或javascript(目前)中没有任何功能可以做到这一点。
当ES7发生时(带有等待),您将。
如果您使用另一个框架或transpiler(如链接的文章所建议的那样-Traceur transpiler或Spawn),您可以。
如果你推出自己的实现,你就可以!
我的方法是用OLD javascript对象创建一个函数,如下所示:
var globalRequestSync = function (pUrl, pVerbo, pCallBack) {
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
pCallBack(httpRequest.responseText);
}
}
httpRequest.open(pVerbo, pUrl, false);
httpRequest.send(null);
};
我最近遇到了这个问题,并创建了一个名为"syncPromises"的实用程序。这基本上是通过发送我所说的"指令列表"来实现的,该列表是按顺序调用的函数数组。您需要调用first-then()来启动,当响应返回指令列表中的下一项时,动态地附加一个新的.then(),因此您需要跟踪索引。
// instructionList is array.
function syncPromises (instructionList) {
var i = 0,
defer = $q.defer();
function next(i) {
// Each function in the instructionList needs to return a promise
instructionList[i].then(function () {
var test = instructionList[i++];
if(test) {
next(i);
}
});
}
next(i);
return defer.promise;
}
我发现这给了我们最大的灵活性。您可以自动推送操作等来构建指令列表,还可以在被调用者函数中附加尽可能多的.then()响应处理程序。您还可以链接多个syncPromises函数,这些函数都将按顺序发生。
- 从Javascript方法返回全局变量
- Meteor方法在客户端返回null,在客户端运行的相同方法返回正确的值
- AngularJS错误:提供程序必须从$get工厂方法返回值
- 修复AngularJS错误:提供程序必须从$get工厂方法返回值
- 从 javascript 中的对象方法返回一个对象
- 为什么我的Mongoose findAll方法返回500错误.
- 角度方法返回未绘制的代码
- 解析查询查找方法返回对象而不是数组
- Jquery Ajax调用没有't点击操作方法/返回整个HTML页面
- ajax方法返回错误时如何打印输出
- Meteor 方法返回客户端和服务器上的不同对象
- 如何将异步方法返回的值发送到javascript中的另一个异步方法
- Javascript getDay方法返回错误的数字
- Coffeescription类中的方法返回函数而不是字符串
- 当使用Q/promises/异步函数时,如何将一个值从一个类方法返回到另一个类
- find()方法返回具有不需要的属性的对象
- 如何在JSF中将toDataURL方法返回的画布内容作为图像存储在磁盘上
- 从请求.js请求方法返回结果
- jQuery的.children()方法返回'undefined'
- Angularjs 控制器在服务方法返回之前从服务中分配变量