Angular $q 完整指南

假如想运用 $http 或许其他异步操纵, 那 $q 是必须要控制的观点啦. Let’s get started!

怎样明白$q, deferred object ?

抽象的解说angular中的$q与promise

假定有一个家具厂,而它有一个VIP客户张先生。

有一天张先生须要一个奢华衣柜,因而,他打电话给家具厂说我须要一个衣柜,转头做好了给我送来,这个操纵就叫$q.defer,也就是延期,由于这个衣柜不是如今要的,所以张先生这是在提议一个可延期的请求。

同时,家具厂给他留下了一个回执号,并对他说:我们做好了会给您送过去,宁神吧。这叫做promise,也就是许诺。

如许,这个defer算是正式建立了,因而他把这件事记录在自身的日记上,而且同时记录了回执号,这叫做deferred,也就是已延期事宜。

如今,张先生就不必再去想着这件事了,该做什么做什么,这就是“异步”的寄义。

假定家具厂在一周后做完了这个衣柜,并履约送到了张先生家(包邮哦,亲),这就叫做deferred.resolve(衣柜),也就是“已处置惩罚”。而这时刻张先生只需签收一下这个(衣柜)参数就好了,固然,这个“邮包”中也不一定只要衣柜,还能够包括别的东西,比方厂家宣扬材料、产物名录等。全部过程当中轻松愉快,谁也没等谁,没有糟蹋任何时候。

假定家具厂在评价后发明这个规格的衣柜我们做不了,那末它就须要deferred.reject(来由),也就是“谢绝”。谢绝没有时候限定,能够发作在给出许诺以后的任何时刻,以至能够发作在快做完的时刻。而且谢绝时刻的参数也不仅仅限于来由,还能够包括一个道歉信,违约金之类的,总之,你想给他什么就给他什么,假如你以为不会触怒客户,那末不给也没紧要。

假定家具厂发明,自身正好有一个相符张先生请求的存货,它就能够用$q.when(现有衣柜)来把这个许诺给张先生,这件事就马上被处置惩罚了,大快人心,张先生可不在意你是从新做的照样现有的制品,只会赞叹于你们的效力之高。

假定这个家具厂对客户分外的仔细,它还能够经由过程deferred.notify(愿望状况)给张先生发送愿望状况的“关照”。

如许,全部异步流程就圆满完成,不管胜利或许失利,张先生都没有往里面投入任何分外的时候本钱。

好,我们再扩大一下这个故事:

张先生此次须要做一个桌子,三把椅子,一张席梦思,然则他不愿望本日收到个桌子,来日诰日收到个椅子,后天又得签收一次席梦思,而是愿望家具厂做好了以后一次性送过来,然则他下单的时刻又是离别下单的,那末他就能够从新跟家具厂要一个包括上述三个许诺的新许诺,这就是$q.all(桌子许诺,椅子许诺,席梦思许诺),

如许,他就不必再关注之前的三个许诺了,直接守候这个新的许诺完成,到时刻只需一次性签收了前面的这些许诺就好了。

怎样建立 promise -1

$q 支撑两种写法, 第一种是类似于ES6规范组织函数写法

$q(function resolver (resolve, reject) {})

注重:

+ ES6 写法并不支撑 progress/notify 的回调函数
+ 在组织函数中抛非常也并不会显式的reject the promise
// var iWantResolve = false;
var iWantResolve = true;

function es6promise() {
    return $q(function (resolve, reject) {
        $timeout(function () {
            if (iWantResolve) {
                resolve("es6promise resolved");
            } else {
                reject("es6promise reject");
            }
        }, 1000)
    })
}

promise 的要领

  • promise.then(successCb, errCb, notifyCb)

  • 个中successCb 将在 promise resolve 后被挪用, errCb 将在 promise reject 后被调

  • notifyCb 将在 deferred.notify 后被挪用, 能够屡次挪用

  • promise.catch == promise.then(null, errCb), 用于处置惩罚之前没有被处置惩罚的 rejected promise

  • promise.finally 将末了被挪用, 平常用于资本开释的清算操纵

es6promise()
    .then(function (data) {
        console.log(data);
    })
    .catch(function (err) {
        console.log(err);
    });

// if(iWantResolve == true) output: es6promise resolved
// if(iWantResolve = false) output: es6promise reject

怎样建立 promise -2

第二种是类似于 commonJS 的写法 $q.deferred()

function commonJsPromise() {
    var deferred = $q.defer();
    $timeout(function () {
        deferred.notify("commonJS notify");
        if (iWantResolve) {
            deferred.resolve("commonJS resolved");
        } else {
            deferred.reject("commonJS reject");
        }

    }, 500);

    return deferred.promise;
}

commonJsPromise()
    .then(function /** success callback**/(data) {
        console.log(data);

    }, function /** error callback **/ (err) {
        console.log(err);
    }, function /** progress callback **/ (update) {
        console.log(update);
    });
 
// if(iWantResolve == true) output: commonJS notify commonJS resolved
// if(iWantResolve = false) output: commonJS notify commonJS reject

$q.all

  • $q.all([promise1, promise1]) 接收一个包括若干个 promise 的数组,

  • 等一切的 promise resolve 后, 其自身 resolve 包括上述效果的数组 [data1, data2]

  • 假如上述 promise 有一个 reject, 那末$q.all() 会把这个 rejected promise 作为其 rejected promise (只要一个哦)

  • progress/notify 的 callback 并没有效

$q.all([es6promise(), commonJsPromise()])
    .then(function (dataArr) {
        console.log("$q.all: ", dataArr);
    }, function (err) {
        console.log("$q.all: ", err)
    }, function /** unnecessary **/ (update) {
        console.log("$q.all", update);
    });
// if(iWantResolve == true) output: $q.all:  ["es6promise resolved", "commonJS resolved"]
// if(iWantResolve = false) output: $q.all:  es6promise reject

$q.reject, $q.when, $q.resolve

  • $q.reject() 马上返回一个rejected 的 promise, 在链式挪用的时刻很有效

  • $q.resolve == $q.when(value, successCb, errorCb, progressCb)

  • value 多是一个 then-able 的 obj(即能够是 $q.defer() 返回的, 也能够是其他库发生的), 也多是恣意数据, 然则 $q.when 终究都邑返回一个 promise

  • $q.when 既能够写成上述的组织函数情势, 也能够写成 $q.when(value).then(fn, fn, fn) 的情势

$q.reject("instant reject")
    .catch(function (err) {
        console.log(err);
    });
// output: instant reject

$q.when(commonJsPromise(),
    function /** success callback **/(data) {
        console.log("$q.when success callback function: " + data);
        return "$q.when success callback return another value";
    })
    .then(function (data) {
        console.log("$q.when then function:" + data);
    });

// if(iWantResolve == true) output: 
// $q.when success callback functionL: commonJS resolved
// $q.when then function:$q.when success callback return another value

// if(iWantResolve = false) output: 
// $q.when err callback function: commonJS reject
// $q.when then function:undefined

$q.when("some value", function (data){
    console.log(data);
})

// output: some value

promise chains 链式挪用

任安在 successCb, errCb 中返回的非 $q.reject()对象, 都将成为一个 resolve 的 promise.
所以能够涌现以下语法 promise.then().then().then()

$q.when("1")
    .then(function (data) {
        console.log(data);
        return $q.reject(2);
    })
    .catch(function (err) {
        console.log(err);
        return 3;
    })
    .then(function (data) {
        console.log(data);
    })
    
// output: 1 2 3 

参考材料

    原文作者:xiaoyu2er
    原文地址: https://segmentfault.com/a/1190000004317947
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞