1. Promise的状态
Promise对象有三个状态:1. 进⾏中(pending)2. 成功(resolved)3. 失败(rejected)
2. ⽣成⼀个Promise对象
1. 构造函数
new Promise(function(resolve,reject){ });
resolve和reject函数是浏览器内部实现的,直接调⽤即可。
2. Promise.resolve
Promise.resolve()直接返回⼀个resolve状态的Promise对象Promise.resolve可以⽤来⽣成⼀个then链
3. Promise.reject
Promise.reject()直接返回⼀个reject状态的Promise对象
3. Promise的then的⽤法
Promise的then永远返回⼀个新的Promise,Promise的catch是then(null,rejection)的语法糖,catch中也会返回⼀个新的Promise。建议在Promise的then永远return或throw,不要只是执⾏⼀个函数。例如:
var aPromise = new Promise(function (resolve) { resolve(100);});
var thenPromise = aPromise.then(function (value) { console.log(value);});
var catchPromise = thenPromise.catch(function (error) { console.error(error);});
console.log(aPromise !== thenPromise); // => trueconsole.log(thenPromise !== catchPromise);// => true
=== 是严格相等⽐较运算符,我们可以看出这三个对象都是互不相同的,这也就证明了 then 和 catch 都返回了和调⽤者不同的promise对象。
1. Promise的then内部可以做三种事情:
(1). return 另⼀个promise
(2). return ⼀个同步值(或者undefined)
因为javascript函数⽆返回值时候,默认返回undefined,所以只是执⾏⼀个函数,不return,默认就是返回undefined。
返回⼀个同步值在Promise中会将同步代码包裹为promise,得到的还是⼀个promsie。返回⼀个同步值是有⽤处的,例如,⼀个异步值在内存中做了缓存,可以直接从内存中拿到该值,直接返回,不必再调⽤异步接⼝。
getUserByName('xxx').then(function(user){ if(imMemoryCache[user.id]){
return inMemoryCache[user.id]; }
return getUserAccountById(user.id);}).then(function(userAccount){});
(3). throw ⼀个同步异常
2. Promise的⼀些写法
new Promise(function(resolve,reject){ resolve(syncValue);}).then(/*...*/)
//可以写成
Promise.resolve(syncValue).then(/*...*/)
//⼀个错误也可以写成
Promise.reject(new Error('...'))
这样⽆论成功或失败都可以后⾯的then和catch中捕获和继续操作
3. Promise的then中只能传递函数,如果为其他类型,例如另⼀Promise,会被解释为null,此时Promsie的值传递会穿透
例如:
Promise.resolve('foo').then(Promise.resolve('bar')).then(function(result){ console.log(result);});
//会被解释为:
Promise.resolve('foo').then(null).then(function(result){ console.log(result);});
第⼀个resolve的值会穿透到then,打印出foo。
4. then的四种写法的区别
// 写法⼀
f1().then(function () { return f2();});
// 写法⼆
f1().then(function () { f2();});
// 写法三
f1().then(f2());// 写法四f1().then(f2);
1. 写法1和4完全等价,f1值能传递到f2,f2的返回值也能继续向后⾯的then传递2. 写法2相当于默认return undefined,⽆法向后⾯的then传递值
3. 写法3能够向后⾯传递f2的值,没有更深刻的解释(有懂的朋友请评论告知)4. Promise的调⽤⽅法
每个then返回⼀个新的promise调⽤,这种写法被称为composing promises。
promise1.then(function(){ return promise2;}).then(function(){ return promise3;}).then(function(){ return promise4;}).catch(function(err){ console.log(err);});
5. Promise的并⾏执⾏
由于promise⼀旦被创建,就会⽴即执⾏,所以拿到⼀个Promise数组时候,其中的promise必然全部开始执⾏了。因此要让⼀系列promise顺序执⾏,只能将promise放在⼀个函数中,在要执⾏的时候才去创建他,就是⼀个⼯⼚函数,promiseFactory。promise并⾏执⾏的代码应该如下:
function executeSequentially(promiseFactories){ var res = Promsie.resolve();
promiseFactories.forEach(function(promiseFactory){ res = res.then(promiseFactory); });
return res;}
//⼯⼚函数只是简单的创建⼀个promisefunction promiseFactory(){ return createAPromise();}
6. Promise捕获错误
7. 实现⼀个Promise版本的ajax
//原⽣版本
function Http(){}
Http.prototype = { get:function(opts){
return this.ajax(opts); },
post:function(){
return this.ajax(opts); },
ajax:function(opts){
return Promise(function(resolve,reject){
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('...'); var {url,method,data,async,success,fail} = options; var sendBody = null;
var qs = Object.keys(data).reduce(function(cur,pre,index){
return pre + '&' + encodeURIComponent(cur) + '=' + encodeURIComponent(data[cur]); },'').slice(1);
if(medthod == 'get'){ url += '?' + qs; }
else if(medhot == 'post'){
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); sendBody = qs || null; }
xhr.onreadystatechange = function(){ if(xhr.readystate == 4){
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ resolve(xhr,xhr.responseText); } } else{
reject(xhr,xhr.responseText); } }
xhr.open(method,url,async); xhr.send(sendBody); }); }}
//jquery版本function Http(){}
Http.prototype = { get:function(opts){
return this.ajax(opts); },
post:function(opts){
return this.ajax(opts); },
ajax:function(){
return $.ajax(opts); }}
参考:https://juejin.im/entry/596f2ab2f265da6c25190f41
http://javascript.ruanyifeng.com/advanced/promise.html#toc2 https://www.kancloud.cn/kancloud/promises-book/44256
因篇幅问题不能全部显示,请点此查看更多更全内容