`
jinhailion
  • 浏览: 46248 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

es6 promise 粗浅个人心得

    博客分类:
  • es6
 
阅读更多
可先参考阮一峰的几篇文章
这里从这篇文章开始《彻底理解Javascript 中的 Promise》
http://doc.okbase.net/libin-1/archive/253716.html

es6在线练习,可以用http://www.es6fiddle.net/

我的理解:
promise对象通常为一段端函数代码,而且通常是一段异步处理才有意义,比如含有settimeout或ajax等。
function prms1(){
	var promise = new Promise(function(resolve, reject){
    	setTimeout(function(){
        	console.log('执行任务1'); //2
          	resolve('执行任务1成功'); //3 --> 导致4调用
        }, 2000);
    });
  	return promise;
}

var prms1 = prms1();
console.log('before then');
prms1.then(function(data){ //1
	console.log('第1个回调: ' + data); //4
})

代码中我标注了执行顺序,promise的then函数用来注册一个将要调用的回调,可以多个then链式写出来,但都不会执行,只是注册。
当在该promise里调用resolve时,设置状态为允许,才能调用执行then里函数。所以是按我标出的顺序执行的。
多加一个then看看效果:
function prms1(){
	var promise = new Promise(function(resolve, reject){
    	setTimeout(function(){
        	console.log('执行任务1'); //2
          	resolve('执行任务1成功'); //3 --> 导致4调用
        }, 2000);
    });
  	return promise;
}

var prms1 = prms1();
console.log('before then');
prms1.then(function(data){ //1
	console.log('第1个回调: ' + data); //4
        //return 'abc';
}).then(function(data){
	console.log('第2个回调: ' + data); //5
});

执行后,控制台输出
before then
执行任务1
第1个回调: 执行任务1成功
第2个回调: undefined

可以看到,后续的then也都会执行,因为then的回调默认将返回当前的promise,保证链式调用像jquery一样,我的理解,如果return的是非promise类型,都被认为返回了当前的promise,且将返回的值带入下个then的回调入参中,可以查看return abc的效果

这样一来,好像这玩意儿也没啥大用处嘛。关键用途在下面,如果return的是一个Promise类型,就可以处理那个promise对象的函数了,并且由它来的resolve来控制它的then的执行,这样,就不会一长串then都被执行了,如下:
function prms1(){
	var promise = new Promise(function(resolve, reject){
    	setTimeout(function(){
        	console.log('执行任务1'); //2
          	resolve('执行任务1成功'); //3 --> 导致4调用
        }, 2000);
    });
  	return promise;
}

function prms2(){
	var promise = new Promise(function(resolve, reject){
    	setTimeout(function(){
        	console.log('执行任务2');
          	//resolve('执行任务2成功');
        },2000);
    });
  	return promise;
}

var prms1 = prms1();
console.log('before then');
prms1.then(function(data){ //1
	console.log('第1个回调: ' + data); //4
  	return prms2();
}).then(function(data){
	console.log('第2个回调: ' + data); 
});

运行后输出
before then
执行任务1
第1个回调: 执行任务1成功
执行任务2

可以看到,第二个then没有再执行了,因为它不受第一个promise控制了,它受prms2创建的新promise控制。将注释的resolve打开,看到
before then
执行任务1
第1个回调: 执行任务1成功
执行任务2
第2个回调: 执行任务2成功


因此,个人理解,在编写多回调嵌套的代码时,可以把每层嵌套放入一个promise对象中,用then来处理,并且注意每个then回调里return下一个promise

angular中,异步逻辑放在then中,具体参照此文章
https://my.oschina.net/ilivebox/blog/293771

var deferred = $q.defer();
var promise = deferred.promise;

// resolve it after a second
$timeout(function() {
  deferred.resolve('foo');
}, 1000);

promise
  .then(function(one) {
    console.log('Promise one resolved with ', one);

    var anotherDeferred = $q.defer(); //在angular里使用promise处理多回调的常规写法

    // resolve after another second
    // $timeout算是第一个异步操作的所有代码
    $timeout(function() {
      //......这里省略异步的操作,在异步的最后resolve下一个promise
      anotherDeferred.resolve('bar'); //在angular里使用promise处理多回调的常规写法
    }, 1000);

    return anotherDeferred.promise; //在angular里使用promise处理多回调的常规写法

  })
  .then(function(two) {
    console.log('Promise two resolved with ', two);
  });

这样就保证了then2里的回调在then1后才执行

在ajax中如此使用和封装
angular.module("MyService", [])
    .factory('githubService', ["$q", "$http", function($q, $http){
        var getPullRequests = function(){
        var deferred = $q.defer();
        var promise = deferred.promise;
        var progress;
        $http.get("https://api.github.com/repos/angular/angular.js/pulls")
        .success(function(data){
            var result = [];
            for(var i = 0; i < data.length; i++){
                result.push(data[i].user);
                progress = (i+1)/data.length * 100;
                deferred.notify(progress);
            }
            deferred.resolve(result);
            })
        .error(function(error){
            deferred.reject(error);
        });
        return promise;
    }

    return {
        getPullRequests: getPullRequests
    };
}]);



在项目中的使用心得
1. 所有基本promise和async里都不处理异常。在最上层的异步调用后才catch异常。否则底层catch后处理了 ,最上层就不会进入catch。
2. 接口的对于code的统一处理可以抽象出来,在最上层复用
3. promise里通过reject抛出异常,async里如果向主动抛出异常,用throw new Error。最终都在最上层调用中捕获到他们
4. reject('xxx') 和 throw new Error('xxx')稍有不同,在catch到e后,前者为e的值,后者为e.message的值
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics