什么是Promise
JavaScript 这门语言是单线程执行的,这就导致一些耗时的操作会阻塞当前运行线程。为了解决这个问题,引入了“同步”和“异步”这两个概念。当多个异步任务需要顺序执行的时候,回调函数层层嵌套便产生了回调地狱。Promise,作为异步编程,回调地域的一种解决方案出现了。
Promise对象具有以下两个特点:
对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:
pending: 初始状态,不是成功或失败状态。fulfilled: 意味着操作成功完成。rejected: 意味着操作失败。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
Promise的优点:可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,以此解决回调地狱问题。并且Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise的缺点:一旦新建就会立刻执行,并且无法取消。并且需要设置回调函数才能在外部获取抛出的错误。处于初始状态panding 时不知道时刚刚开始还是即将完成。
Promise的创建及使用
1.Promise的创建及使用
const fs
= require('fs');
let promise
= new Promise((resolve
, reject
) => {
fs
.readFile('./100.txt', 'utf8', (err
, result
) => {
if (err
!= null) {
reject(err
);
}else {
resolve(result
);
}
});
});
promise
.then((result
) => {
console
.log(result
);
})
.catch((err
)=> {
console
.log(err
);
})
2.链式调用,按顺序执行。解决回调地狱问题
const fs
= require('fs');
function p1 () {
return new Promise ((resolve
, reject
) => {
fs
.readFile('./1.txt', 'utf8', (err
, result
) => {
resolve(result
)
})
});
}
function p2 () {
return new Promise ((resolve
, reject
) => {
fs
.readFile('./2.txt', 'utf8', (err
, result
) => {
resolve(result
)
})
});
}
function p3 () {
return new Promise ((resolve
, reject
) => {
fs
.readFile('./3.txt', 'utf8', (err
, result
) => {
resolve(result
)
})
});
}
p1().then((r1
)=> {
console
.log(r1
);
return p2();
})
.then((r2
)=> {
console
.log(r2
);
return p3();
})
.then((r3
) => {
console
.log(r3
)
})
3.用 Promise 对象实现的 Ajax 操作的例子。
function ajax (options
) {
var defaults
= {
type
: 'get',
url
: '',
data
: {},
header
: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success
: function () {},
error
: function () {}
};
Object
.assign(defaults
, options
);
var xhr
= new XMLHttpRequest();
var params
= '';
for (var attr
in defaults
.data
) {
params
+= attr
+ '=' + defaults
.data
[attr
] + '&';
}
params
= params
.substr(0, params
.length
- 1);
if (defaults
.type
== 'get') {
defaults
.url
= defaults
.url
+ '?' + params
;
}
xhr
.open(defaults
.type
, defaults
.url
);
if (defaults
.type
== 'post') {
var contentType
= defaults
.header
['Content-Type']
xhr
.setRequestHeader('Content-Type', contentType
);
if (contentType
== 'application/json') {
xhr
.send(JSON.stringify(defaults
.data
))
}else {
xhr
.send(params
);
}
}else {
xhr
.send();
}
xhr
.onload = function () {
var contentType
= xhr
.getResponseHeader('Content-Type');
var responseText
= xhr
.responseText
;
if (contentType
.includes('application/json')) {
responseText
= JSON.parse(responseText
)
}
if (xhr
.status
== 200) {
defaults
.success(responseText
, xhr
);
}else {
defaults
.error(responseText
, xhr
);
}
}
}
ajax({
type
: 'post',
url
: 'http://localhost:3000/responseData',
success
: function (data
) {
console
.log('这里是success函数');
console
.log(data
)
}
})
4.Promise.all方法,Promise.race方法
Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例.
var p
= Promise
.all([p1
,p2
,p3
]);
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。 (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
var p
= Promise
.race([p1
,p2
,p3
]);
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的返回值。