1.情景展示
在前端js源码时,遇到了大量的Promise对象的用法,看得是一脸懵逼,Promise到底是个什么?
2.具体分析
在实际开发过程中,我们往往会遇到这样的场景:
以ajax请求为例,我们知道,只有在请求结束后才能进行下一步操作,虽然默认情况下是异步请求,并不影响后续代码的执行;
但是,要在拿到想要的数据进行下一步操作时,这个地方我们是绕不开的,必须是同步的;
如果使用原生的ajax或者jQuery封装的ajax,遇到复杂的业务时,代码写的经常是又臭又长;
为了代码更加具有可读性和可维护性,我们能不能将数据请求与数据处理明确的区分开来呢?
<script type="text/javascript">
$.ajax({
url : '<%=request.getContextPath()%>/ycyl/dcm/view.do?dcmPath=uploadfile/123&RESULT_TYPE=json',
method: 'get',
success: function(response) {
var fileNames = response.fileNames;
for (var i = 0; i < array.length; i++) {
console.log(fileNames[i]);
}
},
error: function(error) {
console.log(error);
}
});
</script>
3.解决方案
Promise对象有三种状态,他们分别是:
- pending: 等待中,或者进行中,表示还没有得到结果
- resolved(Fulfilled): 已经完成,表示得到了我们想要的结果,可以继续往下执行
- rejected: 也表示得到结果,但是由于结果并非我们所愿,因此拒绝执行
这三种状态不受外界影响,而且状态只能从pending改变为resolved或者rejected,并且不可逆。在Promise对象的构造函数中,将一个函数作为第一个参数。而这个函数,就是用来处理Promise的状态变化。
new Promise(function(resolve, reject) {
if(true) { resolve() };
if(false) { reject() };
})
上面的resolve和reject都为一个函数,他们的作用分别是将状态修改为resolved和rejected。
Promise对象中的then方法,可以接收构造函数中处理的状态变化,并分别对应执行。then方法有2个参数,第一个函数接收resolved状态的执行,第二个参数接收reject状态的执行。
then方法的执行结果也会返回一个Promise对象。因此我们可以进行then的链式执行,这也是解决回调地狱的主要方式。
我们可以使用Promise对象来解决数据传递的问题。
前提:在页面中引入jQuery.min.js文件。
我们可以对ajaxGet请求做进一步封装:
function ajaxGet(url) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get',
success: function(response) {
resolve(response);
// resolve(eval('(' + response + ')'));
},
error: function(response) {
reject(response);
// reject(eval('(' + response + ')'));
}
});
});
}
调用方法一:
var url = '<%=request.getContextPath()%>/ycyl/dcm/view.do?dcmPath=uploadfile/123&RESULT_TYPE=json';
ajaxGet(url).then(function(response) {// ajax请求成功,执行reject
var fileNames = response.fileNames;
for ( var i in fileNames) {
console.log(fileNames[i]);
}
}, function(error) {// ajax请求失败,执行reject
console.log(error);
});
ajax走success:
ajax走error:
如果不需要走reject,在调用的时候可以将对该函数的调用,省略。
ajaxGet(url).then(function(response) {
var fileNames = response.fileNames;
for ( var i in fileNames) {
console.log(fileNames[i]);
}
});
调用方法二:
var url = '<%=request.getContextPath()%>/ycyl/dcm/view.do?dcmPath=uploadfile/123&RESULT_TYPE=json';
ajaxGet(url).then(response => {
var fileNames = response.fileNames;
for (let fileName of fileNames) {
console.log(fileName);
}
}, error => console.log(error));
不需要走reject
var url = '<%=request.getContextPath()%>/ycyl/dcm/view.do?dcmPath=uploadfile/123&RESULT_TYPE=json';
ajaxGet(url).then(response => {
var fileNames = response.fileNames;
for (let fileName of fileNames) {
console.log(fileName);
}
});
方法二的执行结果和方法一一样,这里不再展示。
两种方法,只是对匿名函数的调用方式有所区别,但是,效果是一样的。
写在最后
哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!
作者:Marydon