前面有说到处理angularjs中的异步的问题,在福瑞项目中我是通过逻辑判断不停的调用方法判断是否异步的按个函数已经执行完毕的。

这里咱们就来说下angularjs中的异步的问题,以及“正规的解决方法”

先聊一聊关于promise中的异步编程

异步编程存在两种形式,一种是单次执行模式,一种是监听执行模式。$q是解决第一种模式下的问题,promise模式的异步编程能够很好的解决单次执行模式下的一些问题,再说白一点,promise不会产生新的东西只是一个语法糖帮你能够编出更加优雅的异步代码

Promise模式使用一个延期对象defer代表异步执行体,用promise代表回调执行体,defer可以发送信息,promise可以接受信息,然后执行响应的回调函数。

说到这,是不是可以想到富瑞上面的那个问题可以把它们放到promise里进行链式调用了呢?我们继续往下说:

Promise是异步执行体和回调执行体之间的桥梁,这样的好处是异步执行体和回调执行体这种模式很好的对异步动作和回调动作进行了解耦。因为你可以在promise中好好的执行你的回调执行体,而只是接受一个defer发送来的参数。

这里还是没有很好的体现出promise模式的优势,而他真正的优势在于这种模式下扩充的api,。比如promise下的then方法,这种方法可以很好地支持异步链式编程。这里你可能还不了解,说下$q,$q是作为angularJs中的一个服务而存在的,只是对promise模式下异步的一个简单实现版(这里想到了华勤项目中小马哥用到的$q,当时还不好意思问这是啥!)关于$q的api大家可以从网上百度下、这里我就简单的说下

defer对象(延迟对象)可以通$q.defer()获取,下面是defer对象的api:

方法:resolve(value):向promise对象异步执行体发送消息告诉他我已经成功完成任务,value即为发送的消息。reject(value):向promise对象异步执行体发送消息告诉他我已经不可能完成这个任务了,value即为发送的消息。notify(value):向promise对象异步执行体发送消息告诉他我现在任务完成的情况,value即为发送的消息。

  这些消息发送完promise会调用现有的回调函数。

属性:promise即与这个defer对象的承诺对象。

  从上可以看出defer主要是用来发送消息的。

  promise对象可以通过defer.promise获取,下面是promise对象的api:

  方法:

  then(successCallback,errorCallback,notifyCallback):参数为不同消息下的不同回调函数,defer发送不同的消息执行不同的回调函数,消息作为这些回调函数的参数传递。返回值为回一个promise对象为支持链式调用而存在。当第一个defer对象发送消息后,后面的promise对应的defer对象也会发送消息,但是发送的消息不一样,不管第一个defer对象发送的是reject还是resolve,第二个及其以后的都是发送的resolve,消息是可传递的。

  catch(errorCallback):then(null,errorCallback)的缩写。

finally(callback):相当于then(callback,callback)的缩写,这个finally中的方法不接受参数,却可以将defer发送的消息和消息类型成功传递到下一个then中

defer():用来生成一个延迟对象 var defer =$q.defer();

  reject():参数接收错误消息,相当于在回调函数中抛出一个异常,然后在下一个then中调用错误的回调函数。

 all():参数接收为一个promise数组,返回一个新的单一promise对象,当这些promise对象对应defer对象全部解决这个单一promise对象才会解决,当这些promise对象中有一个被reject了,这个单一promise同样的被reject了

when():接收第一个参数为一个任意值或者是一个promise对象,其他3个同promise的then方法,返回值为一个promise对象。第一个参数若不是promise对象则直接运行success回调且消息为这个对象,若为promise那么返回的promise其实就是对这个promise类型的参数的一个包装而已,被传入的这个promise对应的defer发送的消息,会被我们when函数返回的promise对象所接收到。

对上面还有一个注意事项就是defer对象发送消息不会立即执行的,而是把要执行的代码放到了rootScope的evalAsync队列当中,当时scope.$apply的时候才会被promise接收到这个消息。

这里附上一份小马哥在华勤上写的一个代码,我加了些注释:

//请求服务器数据

functionmakeRequest($http,$q,url,params){

//$q是内置服务,所以可以直接使用

try{

vardefered=$q.defer();//声明延后执行,表示要去监控后面的执行

$http.get(url,params)

.success(function(data,status,headers){

//Dosomethingsuccessful

defered.resolve(data);//声明执行成功,即http请求数据成功,可以返回数据了

})

.error(function(data,headers){

//Handletheerror

defered.reject(status+data);//声明执行失败,即服务器返回错误

});

returndefered.promise;//返回承诺,这里并不是最终数据,而是访问最终数据的API


}catch(error){

alert("连接服务发生意外错误");

}

}

下面是对应的调用:

promise.then(function(data){//调用承诺API获取数据.resolve

$scope.user=data;

},function(data){//处理错误.reject

$scope.user={error:'用户不存在!'};

});

最后来说明下关于实现angularjs中的同步请求的三种解决方法

解决方法一:

$http.get('url1').success(function(d1){
$http.get('url2').success(function(d2){


//处理逻辑


});

});

解决方法二:

then中的方法会按顺序执行。

varapp=angular.module('app',[]);

app.controller('promiseControl',function($scope,$http){

functiongetJson(url){

vardeferred=$q.defer();

$http.get(url)

.success(function(d){

d=parseInt(d);

console.log(d);

deferred.resolve(d);

});

returndeferred.promise;

}

getJson('json1.txt').then(function(){

returngetJson('json2.txt');

}).then(function(){
returngetJson('json1.txt');

}).then(function(){
returngetJson('json2.txt');

}).then(function(d){
console.log('end');

});
});

解决方法三

$q.all方法第一个参数可以是数组(对象)。在第一参数中内容都执行完后就会执行then中方法。第一个参数的方法的所有返回值会以数组(对象)的形式传入。

varapp=angular.module('app',$http){

$q.all({first:$http.get('json1.txt'),second:$http.get('json2.txt')}).then(function(arr){

console.log(arr);

angular.forEach(arr,function(d){

console.log(d);

console.log(d.data);

})
});

});

angularJs异步的问题及promise使用的更多相关文章

  1. 详解使用postMessage解决iframe跨域通信问题

    这篇文章主要介绍了详解使用postMessage解决iframe跨域通信问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. swift开发笔记9 - 正向和反向页面传参

    在storyboa里segue是这样的:首先看考勤页面(主页面)如何给备注页面传参:在考勤页面(主页面)的viewcontroller中找到prepareForSegue方法,这个方法由xcode自动生成,用于在使用segue跳转前,做一些处理动作:实际上是通过修改segue的目标页面的某个类属性,从而达到传参的目的。

  3. [快速学会Swift第三方库] Kingfisher篇

    [快速学会Swift第三方库]Kingfisher篇Kingfisher是一个轻量的下载和缓存网络图片库。也可以利用kf_setimageWithURL函数的返回值来进行更多的管理操作下载器自定义下载器参数缓存系统自定义缓存参数预取将一些图片在显示到屏幕上之前,先预取到缓存。动态图片加载动态图片只需要加上一行代码,设置imageView为AnimatedImageView,不设置也能加载,但是在动态图片较大的时候推荐进行该设置。深入学习这里列出了Kingfisher大多数操作,如果想要深入学习Kingfi

  4. swift - 回调

    回调函数B不由该函数的实现方A直接调用,而是在特定的事件或条件发生时由另外的一方C调用,用于对该事件或条件进行响应。在swift中有同步和异步两种形式的回调函数:同步回调函数异回调函数步C调用方法B,B可以是函数或者closureC调用函数B并使B在另一线程上运行B返回之前C处理block状态B和C运行在不同的线程,不会互相block。

  5. 6.3 Swift闭包表达式作为回调函数

    /**闭包表达式作为回调函数*//**上节课中呢,说了闭包表达式的语法,将闭包表达式赋给一个常量并不常用,那种调用方式还不如就写成函数的形式*/vararray=[20,2,3,70,8]showArrayprintbubbleSortletintCmp={->Intin//可以修改闭包表达式//letx=a%10//lety=b%10ifa>b{return-1}elseifaIntin//可以修改闭包表达式letx=a%10lety=b%10ifx>y{return-1}elseifxVoid{for

  6. [译] Alamofire Tutorial: Getting Started

    Alamofire提供了链式的request/response方法,JSON的传参和响应序列化,身份认证和其他特性。Alamofire的优雅之处在于它完完全全是由Swift写成的,并且没有从它的Objective-C版本-AFNetworking那继承任何特性。该token将会被包含在每个发往Imagga的请求的头部。Apple提供JSONSerialization类来帮助将内存中的对象转换为JSON,反之亦然。Alamofire有几个主要功能:.upload:以multipart,流,文件或数据方法上传

  7. 如何在Swift中传递回调函数

    我看过例子,这应该是我想的.我的类的定义是不正确的,因为我传递回调的方式吗?

  8. Android Studio是否支持用于Android UI设计的AngularJS?

    我对AndroidStudio有疑问:AS在设计XML文件时是否支持AngularJS代码,例如:对于小动画或效果?

  9. Android Facebook登录中不会调用回调函数

    解决方法你忘了把监听器放在onActivityResult()中将以下代码放在onActivityResult活动方法中:

  10. android – 如何使用ClientID和ClientSecret在Phonegap中使用Angularjs登录Google OAuth2

    我正尝试使用Angularjs(使用IonicFramework)通过GoogleOAuth2从我的Phonegap应用程序登录.目前我正在使用http://phonegap-tips.com/articles/google-api-oauth-with-phonegaps-inappbrowser.html进行登录.但是当我使用Angular-UI-RouterforIonic时,它正在创建非常

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部