fe ? not exsit ?

走进基础:promise && me ?

记录一下此刻的心情,五味杂陈,每周繁忙的安排着自己,不再像16年刚来北京的时候各种鸡汤人生,以一份美好的工作为憧憬不断学习,现在学习的目的有多少出于真正的兴趣也说不上来了。可唯一最好的也仅能做的就是坚持代码人生。不再信仰成功学,对自己平凡的认识愈来愈深。迷茫了也能慢慢调节自己,虽然对前路仍未可知,依然向往几年后杰出的自己。最近单位来了个实习生,从他身上看到了自己成长的痕迹。身处正门却野路子出家也能做的很棒呀。。起码在目前努力的人之上。。一句话,加油吧。。今天干promise吧,目前与他的关系就是经常用它,似熟悉似不熟悉,今天纪录之。

define

mdn上讲用于异步操作,表示一个现在将来永远不可能用的值。自己的概括为异步操作按期望的顺序来处理,在对象之间传递promise帮忙处理队列。下文中把promise还是叫做她吧。毕竟程序员的浪漫。

background

异步操作的出现的原因: 节省时间能干做a又能做b更加高效率的事情。

异步操作的实现: 事件,回调,promise,async await

异步回调操作的副作用:

  • 嵌套层次很深,金字塔形状的回调地狱(不可维护)。
  • 异步函数是放在另一个新栈开始执行,没办法获取前一个栈的信息,之前的栈没有办法获取异步函数栈抛出的错误,就无法使用trycatch来处理错误。
  • 无法预估异步什么时间完成回调,只能在外层作用域生命变量交给内层作用域使用,导致这些变量可能被更深作用域行为改变,发生未知错误。(多个回调函数之间难以建立联系)
  • 无法正常检索堆栈信息。
  • callback的变量共享,关联的业务模块较多难以维护。

what && how

1
2
3
4
5
6
7
8
9
10
new Promise( (resolve, reject) => {
// todo1 ...
resolve();
// todo ...
reject();
}).then( () => {
// deal resolve
}, () => {
//deal reject
})

先明确她的三个状态: pending、fulfilled、rejected。

有没有发现,她的过程很像一个代理异步的对象,引入一个then回调。执行todo1的过程中为pending状态,毕竟女人都是水做的,直至resolve或者reject把她transform为fulfilled或者rejected状态。立即执行then的响应回调,而且需要明确的是她是坚贞的,她的状态一经改变就不会在发生变化。

1
2
3
4
5
6
7
8
9
//简单demo
new Promise( resolve => {
setTimeout( () => {
console.log('litchi');
resolve();
},3000)
}).then( () => {
console.log('gogogo');
})

关于她的then

如果是resolve中可以传递一个任意值他会生成一个promise类型的value传递给then的回调进行使用;1、参数为两个函数fulfilled和resolve函数。而且会返回一个新的promise对象或者空。2、如若无返回值,会立即执行下一个链式then的调用;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//简单demo
new Promise( resolve => {
setTimeout( () => {
resolve('litchi');
},3000)
}).then( (data) => {
console.log(Object.prototype.toString.call(data)); //[object Promise]
console.log('gogogo');
})

// 如若不
new Promise( (resolve, reject) => {
setTimeout( () => {
console.log('litchi');
resolve('hello');
},1000)
}).then( res => {
//如若不return 一个promise
}).then( data => {
console.log(data); //undefine
})
// 再拉一个例子

new Promise( (resolve, reject) => {
setTimeout( () => {
console.log('litchi');
resolve('hello');
},1000)
}).then( res => {
(function(){
return new Promise( (r,j) => {
setTimeout( () => {
console.log('hi');
r('hi');
}, 2000)
});
}());
return 'i am jackMa';
}).then( data => {
console.log(data);
})
// litchi
// i am jackMa
// hi
// 匿名函数只是个假象

如果then里面还有then, 还是个假象,以顺序队列之行,then返回的仍是promise,等待最内层的promise返回在执行之后的外层then

1
2
3
4
5
6
7
8
9
10
11
12
13
//  吐个槽,个人很容易落下new。。= =。。
// output: 2
new Promise( (r, j) => {
r(1);
}).then( res => {
return new Promise( (r, j) => {
r(2);
}).then(data => {
return data;
})
}).then(res => {
console.log(res);
})

关于她的错误处理

1、交给reject进行错误处理 reject().then(null, () => { //handle error })
2、catch进行错误处理 promise().catch(err => { //handle error })

缺点:无法处理执行栈的基层运行时的错误,但能捕获到异步回调完成的这部分栈信息。

.catch().then()

如若catch没有抛出错误,她仍然返回promise,如果仍有then的队列,仍然可以继续执行。

她的常用函数

promise.all([…arr]);

  • 所有promise完成,它才完成。
  • 其中一个失败则reject。
  • 返回的仍是promise。
  • 参数是数组,如果某元素不是promise,则直接then回调。
1
2
3
4
5
6
7
// output: [1,2]
// 这个时候新返回的promise一直是pending状态,建议reslove掉。
var a = new Promise( (r,j) => { r(1)} );
var b = new Promise( (r,j) => { r(2)} );
Promise.all([a,b]).then(res => {
console.log(res);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//一段伪代码 ajax请求1请求2并行请求,在then里执行结果。
request 1
request 2
return Promise.all([req1,req2].map( (res) => {
return new Promise(r => {
if(res.code == 200) {
resolve(res.data);
}
})
} )).then( data => {
//todo data
}).catch(err => {
throw err;
})

Promise.resolve()

//返回一个fulfilled的promise实例

  • 参数为空或者非promise 则返回fulfilled实例
  • 若为promise,则直接返回
  • 若果是一个thenable,直接调用then

Promise.reject()

//返回一个reject的promise实例

  • 参数为空或者非promise 则返回fulfilled实例
  • 若为promise,则直接返回

Promise.race([…arr])

//用于网络超时提示用户

  • 一个promise完成,它就算完成。
  • 但是arr里面的每个元素都会执行。

应用

babel-polyfill来兼容hack
fetch api 具体应用

总结 

后续会封装一个ajax请求的例子,仍然会补充完善该篇博客。对于async/await 也会后续补充到另一片博客。该篇博客对理解加深了一步把,但能够对人讲述promise的知识点了,有没有!😄😄😄