promise真的是重点中的难点
用fs.readFile()方法顺序读取三个文件,此时:
var fs = require("fs");
function duwenjian(url,callback){
fs.readFile(url,(err,data)=>{
if (err){
callback(err);
return;
}
callback(data)
})
}
fs.readFile("./txt/1.txt",(err,data)=>{
console.log(data.toString());
fs.readFile("./txt/2.txt",(err,data)=>{
console.log(data.toString());
fs.readFile("./txt/3.txt",(err,data)=>{
console.log(data.toString());
});
});
});
回调套回调,因为readFile是异步函数。
Promise表示“承诺”。
⦁ Promise在使用的时候,一定是作为一个函数的return值返回的。
下面的duwenjian(读文件)函数就return了一个Promise对象。这个函数称之为“Promise函数”
⦁ resolve 表示成功的时候调用的函数,
resolve是谁呢?是你then的时候逗号前的函数。
⦁ reject表示失败的时候调用的函数,
reject是谁呢?是你then的时候逗号后的函数。
⦁ 在new Promise((resolve,reject)=>{})函数里面要写具体的异步义务。
⦁ then表示“然后”,在then()、then()、then()中往往是return一个duwenjian函数。
var fs = require("fs");
function duwenjian(url){
return new Promise((resolve , reject) => {
fs.readFile(url , (err , data) => {
if(err){
reject(err);
return;
}
resolve(data);
});
});
}
duwenjian("./txt/1231231.txt")
.then(
(data)=>{
console.log(data.toString());
return duwenjian("./txt/2.txt");
},
(err)=>{
console.log("读取失败");
}
)
.then((data)=>{
console.log(data.toString());
return duwenjian("./txt/3.txt");
})
.then((data)=>{
console.log(data.toString());
})
Promise的总结:原来的回调套回调,现在通过:
- 给函数加一个return new Promise((resolve,reject)=>{})壳
- 调用的时候增加.then()
轻松把回调套回调变为了火车。
ES7中的async和await
ES6中确实优雅的解决了回调黑洞的问题,但是尼玛火车黑洞来了。
ES7变得更优雅。
首先,那个返回Promise对象的函数,没有任何的变化!下面duwenjian函数没有发生任何变化
var fs = require("fs");
function duwenjian(url){
return new Promise((resolve , reject) => {
fs.readFile(url , (err , data) => {
resolve(data.toString());
});
});
}
//异步函数
async function main(){
var data1 = await duwenjian("./txt/1.txt");
console.log(data1);
var data2 = await duwenjian("./txt/2.txt");
console.log(data2);
var data3 = await duwenjian("./txt/3.txt");
console.log(data3);
}
main();
async、await最牛的在于:将异步语句变为了同步语句!
我们用jQuery中的animate()函数来做例子,页面上4个盒子,要求依次动画,一个动完一个动。
//传统:
$("#box1").animate({"left":1000},1000,function(){
$("#box2").animate({"left":1000},1000,function(){
$("#box3").animate({"left":1000},1000,function(){
$("#box4").animate({"left":1000},1000,function(){
});
});
});
});
现在我们可以用async和await结合Promise函数来轻松解决回调黑洞:
//四个盒子依次从左向右运动
function dong(id){
return new Promise((resolve)=>{
$(id).animate({"left":1000},1000,resolve);
});
}
async function main(){
await dong("#box1");
await dong("#box2");
await dong("#box3");
await dong("#box4");
}
main();
需要注意的是:
- 要用async、await,必须事先有一个Promise产生器;
- 写await语句的函数之前必须加async标记;
- await后面必须跟着一个Promise函数的调用;
- 在Promise对象的(resolve,reject)=>{}函数里面,必须有resolve,表示此异步函数已经执行完毕。
- await等号左边将自动成为resolve函数中的参数。
<script type="text/javascript">
function duwenjian(url){
return new Promise((resolve , reject) => {
$.get(url , function(data){
resolve(JSON.parse(data));
});
});
}
async function main(){
var data1 = await duwenjian("txt/1.txt").then(data=>data.result);
var data2 = await duwenjian("txt/2.txt").then(data=>data.result);
var data3 = await duwenjian("txt/3.txt").then(data=>data.result);
console.log(data1);
console.log(data2);
console.log(data3);
}
main();
</script>
最后说一点,就是awaite的函数也可以有then(),then()里return的东西,会被等号左边接收。
<script type="text/javascript">
function duwenjian(url){
return new Promise((resolve , reject) => {
$.get(url , function(data){
resolve(JSON.parse(data));
});
});
}
async function main(){
var data1 = await duwenjian("txt/1.txt").then(data=>data.result);
var data2 = await duwenjian("txt/2.txt").then(data=>data.result);
var data3 = await duwenjian("txt/3.txt").then(data=>data.result);
console.log(data1);
console.log(data2);
console.log(data3);
}
main();
</script>
3 fetch()
fetch是ES8中定稿的一个功能,是一个Ajax函数的升级版。天生可以跨域,不需要jQuery。
fetch()函数的最大优点是天生返回一个Promise对象,所以就不用封装promise,所以就可以结合then()、async、await轻松解决回调套回调的问题。
<script type="text/javascript">
async function main(){
var data1 = await fetch("./txt/1.txt").then(data=>data.json());
var data2 = await fetch("./txt/2.txt").then(data=>data.json());
var data3 = await fetch("./txt/3.txt").then(data=>data.json());
console.log(data1);
console.log(data2);
console.log(data3);
}
main();
</script>
fetch函数也可以发POST请求:
fetch("/search/project/", {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: "JSON的字符串形式"
}).then(function(response) {
});