1. 为何产生promise?
- 相信大家在写JS的时候写过回调函数,当写了多层回调的时候,逻辑已经很难理清楚了,这就是promise解决的问题: 回调地狱
- 多层嵌套的回调中,有同步/异步的方法,那么执行顺序会混乱,而promise采用链式调用。
2. 什么是promise?
所谓promise, 翻译成中文为“承诺, 诺言”, 比如, 你承诺这个月挣钱了给你老婆买一个包, 那么你先去挣钱, 等挣钱了就立刻给老婆买包,实现你的诺言,没挣到钱就立马道歉。换成代码就是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// 先许下承诺
const geilaopomaibao = new Promise((resolve, reject) => {
// 开始挣钱了
if (money) {
// 挣到了
reslove('10k');
} else {
// 没挣着钱
reject('因为没发工资,这个月没挣到钱');
}
})
// 不管挣没挣到钱,要给老婆一个交代。
geilaopomaibao.then(
res => {
// res就是挣到的钱
maibao(res);
},
reason => {
// 道歉
// reason 就是理由
}
);promise是一种规范,也就是大家都可以实现自己的promise,只要遵循规范,都是可以的。在ES6中也正式引入了promise,当然还有很多库去实现了promise规范,列如: Q,bluebird
规范:
Promises/A+
Promises/A+ 中文3. 如何使用promise?
- 首先来个简单的列子:
1
2
3
4
5
6
7
8
9
10const task = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功');
}, 3000);
})
task.then((res) => {
// 3秒后打印成功
console.log(res);
})看这个列子似乎没什么特别之处,感觉就是把callback换成resolve, 那么再看看下面一个
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// 获取列表之前,需要先判断是否登录,then的链式调用
new Promise((resolve, reject) => {
$.ajax('/api/user/login', {
success: function(isLogin) {
if (isLogin) {
resolve(data);
} else {
reject('没有登录');
}
}
})
}).then(
res => {
$.ajax('/api/list', {
success: function(data) {
resolve(data);
}
})
},
reason => {
alert(reason)
}
).then((data) => {
// data为list数据
// 在这里还可以为list排序
return data.sort();
}).then((list) => {
// 好了,这里的拿到list 可以使用了
})promise有几个静态方法,无需实例化既可使用;
Promise.all() (传入一个promise数组, 等待所有代码完成, 或第一个代码失败)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const task1 = {ji: 2018};
const task2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('2018年');
}, 5000);
});
const task3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('新年好');
}, 2000);
});
Promise.all([task1, task2, task3]).then(values => {
console.log(values);
// 5秒后打印 [{ji: 2018}, '2018年', '新年好']
});Promise.race() (传入一个promise数组,当其中一个完成或失败,则采用该promise值)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const task2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('2018年');
}, 5000);
}); ;
const task3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('新年好');
}, 2000);
});
Promise.race([task1, task2, task3]).then(values => {
console.log(values);
// 2秒后打印 '新年好'
});Promise.resolve() (传入一个值,返回一个同步执行成功状态的promise, 适用于: 如果有方法要求返回一个promise, 但你已经有一个值了, 则这个时候使用)
1
2
3
4
5
6
7
8
9/**
* @param {Promise} fn 需要传入一个promise对象
*/
const task = (fn) => {
fn.then()
// ........
}
Promise.resolve(1);- Promise. reject() (传入一个值,返回一个同步执行的失败状态的promise)
- 首先来个简单的列子:
4. 实现一个promise
1 | class Promise { |