文档章节

关于angularjs中的异步请求

邪气小生
 邪气小生
发布于 2015/11/20 17:59
字数 1695
阅读 3358
收藏 7

前面有说到处理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接收到这个消息。

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

//请求服务器数据
function makeRequest($http,$q,url,params){
 
// $q 是内置服务,所以可以直接使用 
  try{
    var defered=$q.defer();  // 声明延后执行,表示要去监控后面的执行  
  
    $http.get(url,params )
  
    .success(function(data, status, headers) { 
    // Do something successful
    defered.resolve(data); // 声明执行成功,即http请求数据成功,可以返回数据了 
    })
    .error(function(data, status, headers) { 
    // Handle the error
    defered.reject(status+data); // 声明执行失败,即服务器返回错误  
    });
     return defered.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中的方法会按顺序执行。

var app = angular.module('app',[]);
 
app.controller('promiseControl',function($scope,$q,$http) {
 
    function getJson(url){
 
        var deferred = $q.defer();
 
        $http.get(url)
 
            .success(function(d){
 
                d = parseInt(d);
 
                console.log(d);
 
                deferred.resolve(d);
 
            });
 
        return deferred.promise;
 
    } 
     getJson('json1.txt').then(function(){
 
        return getJson('json2.txt');
 
    }).then(function(){
 
        return getJson('json1.txt');
 
    }).then(function(){
 
        return getJson('json2.txt');
 
    }).then(function(d){
 
        console.log('end');
 
    });
 
});


解决方法三

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

var app = angular.module('app',[]);
 
app.controller('promiseControl',function($scope,$q,$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);
 
        })
 
    });
 
});


© 著作权归作者所有

邪气小生
粉丝 24
博文 52
码字总数 67752
作品 0
朝阳
程序员
私信 提问
Angular 6.0正式版发布,都有哪些新功能

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 在Angular 5发布半年之后,Angular 6在昨天正式发布,那么在这个版本有哪些新功能呢?新版本重点关注工具链以及工具链在...

异步社区
2018/05/08
0
0
如何优雅的使用 Angular 表单验证

随便说说,这一节可以跳过 去年参加 ngChine 2018 杭州开发者大会的时候记得有人问我: Worktile 是什么时候开始使用 Angular 的,我说是今年(2018年) 3 月份开始在新模块中使用最新的 An...

why520crazy
01/15
0
0
试读angular源码第二章:引导模块bootstrapModule

前言 今天 angularv8的正式版发了,但是除了动态路由那里没觉得有啥大变化,有点小失望 承接上一章 项目地址 文章地址 angular 版本:8.0.0-rc.4 欢迎看看我的类angular框架 引导模块 Angula...

全菜工程师
05/30
0
0
《AngularJS学习整理》系列分享专栏

《AngularJS学习整理》系列分享专栏 《AngularJS学习整理》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201748.html 文章 教你用AngularJS框架一行JS代码实现...

开元中国2015
2018/11/09
190
0
ngular2 VS Angular4 深度对比:特性、性能

在Web应用开发领域,Angular被认为是最好的开源JavaScript框架之一。 Google的Angular团队已于3月23日发布了Angular4,而期待已久的Angular2版本则是之前版本的完全重构。 对于成熟的开发人员...

机器的心脏
2018/06/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

视频如何加水印?

很多视频制作者的视频都被他人盗用过,为了防止自己的劳动成果被他人窃取,给视频加水印对于视频制作者来说,是一件非常重要的事情。那么下面分享一个手机给视频加水印的方法,一起来看看吧!...

白米稀饭2019
20分钟前
3
0
004-Envelop-基于Blockstack的文件传输dapp

本篇文章主要介绍基于Blockstack的文件传输工具; ####A-链接地址 官网地址:https://envelop.app/ Github地址:https://github.com/envelop-app ####B-特性: 1: Share private files easil...

Riverzhou
23分钟前
5
0
SpringCloud——声明式调用Feign

Feign声明式调用 一、Feign简介 使用Ribbon和RestTemplate消费服务的时候,有一个最麻烦的点在于,每次都要拼接URL,组织参数,所以有了Feign声明式调用,Feign的首要目标是将Java HTTP客户端...

devils_os
29分钟前
5
0
《JAVA核心知识》学习笔记 (22. 数据结构)

22.1.1. 栈(stack) 栈( stack)是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶 (top)。它是后进先出(LIFO)的。对栈的基本操作只有 push(进栈)和 pop(出栈...

Shingfi
34分钟前
5
0
你对AJAX认知有多少(1)?

AJAX(一) AJAX技术对于前段或者后端工程师来说,都是必不可缺的 那我们这几期都来细细品味一下AJAX的相关知识,直接上干货喽~ 1、什么是AJAX,为什么要使用Ajax(请谈一下你对Ajax的认识) 什么...

理性思考
42分钟前
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部