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:

js Promise用法示例_ajax

 

ajax走error:

js Promise用法示例_json_02

如果不需要走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