javascript是单线程语言(单线程/多线程、阻塞/非阻塞、同步、异步)参考此文章,全部的任务都是按顺序执行的,可是对于很耗时的操做采用异步的方式(前一个任务结束的时候,不是执行下一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行)参考此文章,js中异步编程的四种方法:回调函数、事件监听、发布/订阅、Promise对象,这里讨论promise的用法,promise是es6增长的内容,使得在异步编程中不用过多的嵌套回调函数,让异步操做变得更加简单javascript
Promise构造函数接收一个函数做为参数,此函数又有两个参数分别为resolve和reject,这两个参数也是函数php
const promise = new Promise(function(resolve, reject) {
// 异步操做的代码
if(success) {
return resolve(data); // data为异步操做成功返回的数据
} else {
return reject(error); //data为失败时返回的数据
}
})
复制代码
promise对象相似于一个容器(也能够说是一个状态机),里面包含着异步操做,异步操做会有两种结果:成功或失败。当异步操做成功就会将pending(执行中状态)转为fulfilled(成功状态)同时触发resolve函数,用来将操做成功后获得的结果传递出去;当异步操做失败就会将pending(执行中状态)转为reject(拒绝状态)同时触发reject函数,用来将操做失败后报出的错误传递出去java
const promise = new Promise(function(resolve, reject) {
// 异步操做的代码
if(success) {
return resolve(data); // data为异步操做成功返回的数据
} else {
return reject(error); //data为失败时返回的数据
}
})
复制代码
咱们来看下面代码:ios
function fn1() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn1')
},1000)
})
}
function fn2() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn2')
},2000)
})
}
fn1().then(fn2)
复制代码
输出为:
fn1
fn2函数不执行,这个时候咱们须要调用resolve函数以便执行then()方法中的回调函数fn2es6
function fn1() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn1')
resolve('fn1')
},1000)
})
}
复制代码
输出为:
fn1
fn2
若是咱们在fn1中调用reject函数时会出现什么状况呢?ajax
function fn1() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn1')
// resolve('fn1')
reject('错误'+'fn1')
},1000)
})
}
fn1().then(fn2).then((data) => {
console.log(data)
})
复制代码
输出为:编程
fn1().then(fn2).then((data) => {
console.log(data)
}, (err) => {
console.log(err)
})
复制代码
输出为:json
当promise实例生成之后,后面跟then方法,其的第一个回调函数来处理resolve函数传递的数据,第二个回调函数来处理reject函数传递的数据,以上的流程用代码展现以下axios
promise
.then(function(data){
//拿到返回的数据以后作一些处理
console.log(data)
}, function(error) {
//返回失败时作一些处理
console.log(error)
})
复制代码
then()方式是Promise实例的方法,此then方法定义在原型对象(Promise.prototype)上,then()方法的返回值是一个新的Promise实例(不是原来那个Promise,原来那个Promise已经承诺过)因此咱们能够采用链式的写法segmentfault
var p1 = new Promise( (resolve, reject) => {
setTimeout(() => resolve('p1'), 10);
});
p1.then( ret => {
console.log(ret);
return 'then1';
}).then( ret => {
console.log(ret);
return 'then2';
}).then( ret => {
console.log(ret);
});
复制代码
执行顺序:
p1>then1>then2
从第二个then()方法开始,它们的resolve中的参数就是前一个then()中的resolve的return语句的返回值 采用链式的then,能够指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的仍是一个Promise对象(即有异步操做),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);}).then(function funcA(comments) {
console.log("resolved: ", comments);}, function funcB(err){
console.log("rejected: ", err);})
复制代码
上面代码中,第一个then方法指定的回调函数,返回的是另外一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。若是变为resolved,就调用funcA,若是状态变为rejected,就调用funcB。 若是采用箭头函数,上面的代码能够写得更简洁
getJSON("/post/1.json").then(
post => getJSON(post.commentURL)).then(
comments => console.log("resolved: ", comments),
err => console.log("rejected: ", err));
复制代码
promise链式写法以下:
function fn1() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn1')
resolve('fn1')
},1000)
})
}
function fn2() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn2')
resolve('fn2')
},2000)
})
}
function fn3() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn3')
resolve('fn3')
},3000)
})
}
function fn4() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn4')
resolve('fn4')
},4000)
})
}
fn1().then(fn2).then(fn3).then((data) => {
console.log(data)
}, (err) => {
console.log(err)
})
复制代码
依次输出为:fn1>fn2>fn3
同时咱们还能够更改执行的前后顺序
function fn1() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn1')
reject(false)
},1000)
})
}
function fn2() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn2')
resolve('fn2')
},2000)
})
}
function fn3() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn3')
resolve('fn3')
},3000)
})
}
function fn4() {
return new Promise(function(resolve, reject){
setTimeout(() => {
console.log('fn4')
resolve('fn4')
},4000)
})
}
fn1().then(fn2).then(fn3).then((data) => {
console.log(data)
}, (err) => {
if(err == false){
fn3().then(fn4)
}
})
复制代码
输出为:fn1>fn3>fn4
咱们在开发时倾向于用catch()方法来处理异常,而不是在then()方法里写入第二个回调函数,这种写法相似于.then(null, rejection)
promise
.then(function(data){
//拿到返回的数据以后作一些处理
console.log(data)
})
.catch(function(error) {
//返回失败时作一些处理
console.log(error)
}
复制代码
为何要采用这么catch()方法呢?咱们来看一个例子:
const promise = new Promise((resolve,reject) => {
console.log(1)
resolve('成功')
})
promise
.then((data) => {
console.log(data)
console.log(a)
}, (err) => {
console.log(err)
})
复制代码
输出为:
1
成功
可是没有捕捉到回调函数里a未定义 这个时候咱们来该写以上代码
1
成功
ReferenceError: a is not defined
Promise对象的Error对象具备冒泡性质,会一直向后传递,直到被捕获为止。也就是说,错误老是会被下一个catch语句捕获
var p = new Promise( (resolve, reject) => {
setTimeout(() => resolve('p1'), 10);
});
p.then( ret => {
console.log(ret);
throw new Error('then1');
return 'then1';
}).then( ret => {
console.log(ret);
throw new Error('then2');
return 'then2';
}).catch( err => {
// 能够捕抓到前面的出现的错误。
console.log(err.toString());
});
复制代码
输出为:
p1
Error: then1
既然catch()是.then(null, rejection)的别名,那么catch()就会返回一个Promise对象,所以在后面还能够接着调用then方法
var p = new Promise((resolve, reject) => {
resolve(x + 2);
});
p.then( () => {
console.log('nothing');
}).catch( err => {
console.log(err.toString());
return 'catch';
}).then( ret => {
console.log(ret);
});
复制代码
输出为:
ReferenceError: x is not defined
catch
当出错时,catch会先处理以前的错误,而后经过return语句,将值继续传递给后一个then方法中,若是没有报错,则跳过catch,示例以下:
var p = new Promise((resolve, reject) => {
resolve('p');
});
p.then( ret => {
console.log(ret);
return 'then1';
}).catch( err => {
console.log(err.toString());
return 'catch';
}).then( ret => {
console.log(ret);
});
复制代码
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
复制代码
var http = {
get: function(url) {
var promise = new Promise(function(resolve, reject) {
$.ajax({
url: url,
method: 'get',
success: function(data) {
resolve(data);
},
error: function(xhr, statusText) {
reject(statusText);
}
});
});
return promise;
}
};
http.get('data.php').then(function(data) {
document.write(data);
}, function(err) {
document.write(err);
});
复制代码
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
var loadImage1 = loadImageAsync(url);
loadImage1.then(function success() {
console.log("success");
}, function fail() {
console.log("fail");
});
复制代码
function fetch(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, params)
.then(response => {
resolve(response.data);
}, error => {
reject(error);
})
.catch(error => {
reject(error)
})
})
}
function lineStatus(params) {
return fetch('/ProductionLine/GetStatus', params)
}
function statisticsData(params) {
return fetch('/ProductionLine/GetWeightStatistics', params)
}
lineStatus(this.lineId)
.then((result) => {
this.deviceStatus.run = result.TotleMoveMotor
this.deviceStatus.stop = result.TotleStopMotor
this.deviceStatus.lost = result.TotleLoseMotor
this.deviceStatus.alarm = result.TotleAlarmMotor
this.ProductionStatus = result.ProductionStatus
console.log(result)
})
.catch((error) => {
console.log('瓦特了...(;′⌒`)')
})
statisticsData(this.lineId)
.then((result) => {
this.outputData.totalOutput = result.MainConveyorModel.OutPut
this.outputData.instantWeight = result.MainConveyorModel.InstantWeight
this.outputData.runningTime = result.MainConveyorModel.RunningTime
this.outputData.motorLoad = result.MainConveyorModel.MotorLoad
// console.log(result)
})
.catch((error) => {
console.log('瓦特了...(;′⌒`)')
})
复制代码
以上是Promise在开发中常见的用法,参考了如下几篇文章,特此感谢做者