Promise

初步了解Promise

参考链接:

吕大豹 大白话讲解Promise(一)

Promise/A+规范

linkFly6/Promise

jQuery中的异步操作管理

$.ajax()对象

说明:主要用于异步请求,提供了success等Deferred的语法糖。

常用方法:

  1. success
  2. error
  3. complete(指无论success或者error都会执行的操作。)
  4. ...

示例(偷懒,直接从项目代码中接下来了0_0,看个样子就好。)

//complete
{
    //...
    getEngageTimeData: function (){
        var _self = this;
        $.ajax({
            type:'POST',
            url:baseUrl + 'getShowDatetime',
            data:{},
            success: function (response){
                var response = JSON.parse(response);
                if(response.status == 0){
                    _self.renderEngageTime(response);
                }
            },
            error:function(){},
            complete: function (msg){
                console.log('总是会执行的方法', msg);
            }
        });
    }
}

//then
{
    //...
    getEngageTimeData:function (){
        var _self = this;
        $.ajax({
            type:'POST',
            url:baseUrl + 'getShowDatetime',
            data:{}
        }).then(function (response){
            var response = JSON.parse(response);
            if(response.status == 0){
                _self.renderEngageTime(response);
            }
        }, function (){
            console.log('发生错误');
        });
    }
}

$.ajax()方法返回的对象不含resolve、reject等方法。

$.Deffered()对象

说明:主要是对异步操作的管理,实现了Promise规范。

常用的方法:

  1. done
  2. fail
  3. always
  4. then
  5. ...

它的方法与ajax对象的方法的对应关系是:

graph LR
done-->success
fail-->error
always-->complete
then-->function(done, fail)
Deffered方法-->ajax方法返回的是受限的Deffered对象

$.whenjQuery的全局方法

说明:异步操作并行执行,然后执行回调。

示例:

function async1() {
    var defer = $.Derferred();
    setTimeout(function() {
        console.log(1);
        defer.resolve('1');//'1':参数表示异步操作返回的数据;
    }, 1000);
    return defer.promise();
}
function async2() {
    //...
}
function async3() {
    //...
}
$.when(async1(), async2(), async3()).then(function(data1, data2, data3) {
    console.log('执行完毕');
    console.log(data1, data2, data3);
});

ES6(也就是ES2015)中的Promise规范

首先看图:
image

可以看出Promise为一个构造函数,包含all、race、reject、resolve这四个主要的方法。其中:

all对应$.when,可以管理多个异步操作的并行执行,然后等最慢的那个异步操作执行完毕后,执行回调。

var async1 = function() {
    var p = new Promise(function(resolve, reject) {
    
        //异步操作
        resolve(data);  //异步操作返回的data数据
    });
    return p;   //因为使用new构造器时,会立即开始执行异步操作,所以需要包装在async1函数中,通过调用该函数执行想要进行的异步操作。
};

//$.when
$
.when(async1(), async2())
.then(function(data1, data2) {
    console.log('所有异步操作执行完毕');
    console.log(data1, data2);  //各个异步操作返回的data值作为回调函数的参数。
});
//Promise.all
Promise
.all([async1(), async2()])
.then(function(data) {
    console.log('所有异步操作执行完毕');
    console.log(data);  //data数组:n个异步操作返回的data值组成的数组。
});

race也可以管理多个异步操作的并行执行,和all不同的是:race是等待最快的那个异步操作执行完毕后,执行回调

var async1 = function() {
    var p = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('async1');
            resolve('1');
        }, 1000);
    });
    return p;
};
var async2 = function() {
    var p = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('async2');
            resolve('2');
        }, 2000);
    });
    return p;
};
var async3 = function() {
    var p = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('async3');
            resolve('3');
        }, 3000);
    });
    return p;
};
Promise
.race([async1(), async2(), async3()])
.then(function(data) {
    console.log('执行回调');
    console.log(data);
});
//输出顺序为:
//async1
//执行回调
//1
//async2
//async3

reject一般用来处理异步操作过程中报错的情况,通常和catch配合使用

ps:catch方法和try{}catch(e){}中的catch类似,用来执行reject的回调或者捕获resolve回调执行过程的错误信息,并进行处理。

//情形一
var async1 = function() {
   var p = new Promise(function(resolve, reject){
		setTimeout(function() {
			console.log('123');
			if(true) {
				reject('出错误了');
			}else {
				resolve('1');
			}
		}, 1000);
   });
   return p;
};
async1()
.then(function(data) {
	console.log('执行结果', data);
})

//作为reject的回调执行
.catch(function(msg) {
	console.log('错误信息:', msg);
});

//输出信息
//123
//错误信息:出错误了

//情形二
var async2 = function() {
   var p = new Promise(function(resolve, reject){
		setTimeout(function() {
			console.log('123');
			if(false) {
				reject('出错误了');
			}else {
				resolve('2');
			}
		}, 2000);
   });
   return p;
};
async2()
.then(function(data) {
    console.log('执行结果', data);
    console.log(zgatry);    //未定义变量
})

//捕获resolve的回调执行过程中发生的错误。
.catch(function(msg) {
    console.log('错误信息:', msg);
});

//输出信息
//123
//执行结果2
//错误信息:ReferenceError: zgatry is not defined at <anonymous>:16:17

ps:执行回调的过程中的错误信息需要通过catch来捕获,否则error会冒泡到全局环境下。

image

resolve和$.Deferred().resolve方法用法类似。

链式调用

var async1 = function() {
   var p = new Promise(function(resolve, reject){
		setTimeout(function() {
			if(false) {
				reject('1出错误了');
			}else {
				resolve('1');
			}
		}, 1000);
   });
   return p;
};
var async2 = function() {
   var p = new Promise(function(resolve, reject){
		setTimeout(function() {
			if(false) {
				reject('2出错误了');
			}else {
				resolve('2');
			}
		}, 2000);
   });
   return p;
};
async1()
.then(function(data1) {
	console.log('第一步执行完毕data1:', data1);
	//console.log(error1);
	return async2();
})
.then(function(data2) {
	console.log('第二步执行完了data2:', data2);
	//console.log(error2);
})
.catch(function(reason) {
	console.log('错误信息', reason);
});

执行结果:

image

如果取消error1和error2的注释,则执行结果如下:

image

说明:前面的异步操作发生错误(执行了reject回调或者resolve回调中发生未知错误)会直接跳过后面的所有操作,由catch捕获并处理错误信息。

Promise回顾和补充

  1. Promise是对延迟(deferred)和异步(asynchronous )操作的管理,可以在Js的同步代码中为某个异步操作完成后,执行回调。通过Promise对象封装,可以实现异步代码的扁平化管理,看起来更加优雅,也更符合书写逻辑,提高代码的可读性。
  2. Promise对象有三种状态
    • pending:初始状态
    • fulfilled:成功的操作
    • rejected:失败的操作
  3. 术语补充
    • promise是一个包含了兼容promise规范then方法的对象或函数,
    • thenable 是一个包含了then方法的对象或函数。
    • value 是任何Javascript值。 (包括 undefined, thenable, promise等).
    • exception 是由throw表达式抛出来的值。
    • reason 是一个用于描述Promise被拒绝原因的值。
  4. 浏览器兼容性
    • 原生的Promise对象仅支持ES5的现代浏览器可以使用。
    • jQuery的$.Deferred对象是从jQuery1.5.0版本开始引入的。

image

持续补充。
time:2016-12-13

posted @ 2017-02-07 16:09  君寻不惑  阅读(315)  评论(0编辑  收藏  举报