回调与promise
方法 用于请求数据(模拟)
resolve代表成功时要做的事情
function f() {
return new Promise(resolve => {
setTimeout(function() {
resolve();
}, 1000);
})
}
f()
.then(function() {
console.log(1);
//return promise实例,才能继续.then()
return f();
})
.then(function() {
console.log(2);
return f();
})
.then(function() {
console.log(4);
return f();
})
.then(function() {
console.log(3);
return f();
})
.then(function() {
console.log(5);
return f();
})
.then(function() {
console.log(6);
});
案例:
Promise 新建后立即执行,所以首先输出的是Promise,然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出
let promise=new Promise(resolve=>{
console.log('Promise');
resolve();
});
promise.then(function(){
console.log('resolved');
});
console.log('Hello!');
//结果:Promise Hello! resolved
Promise小动画案例:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#el {
width: 100px;
background: green;
transition: all 1s;
color: white;
line-height: 100px;
text-align: center;
font-size: 40px;
}
</style>
</head>
<body>
<div id="el">哦</div>
<button id="btn">开始</button>
<script src="./main.js"></script>
</body>
</html>
main.js
function moveTo(el, x, y) {
return new Promise(resolve => {
el.style.transform = `translate(${x}px, ${y}px)`;
setTimeout(function() {
resolve();
}, 1000);
});
}
let el = document.querySelector('div');
document.querySelector('button').addEventListener('click', e => {
moveTo(el, 100, 100)
.then(function() {
console.log('第一次移动');
return moveTo(el, 200, 200);
})
.then(function() {
console.log('第二次移动');
})
.then(function() {
console.log('第二次移动');
});
});
错误处理
resolve成功时操作
reject失败时操作
function f(val) {
return new Promise((resolve, reject) => {
if (val) {
resolve({ name: '小明' });
} else {
reject('404');
}
});
}
f(true)
.then((data) => {
console.log(data)
}, e => {
console.log(e);
})
catch
使用实例的catch方法 可以捕获错误
f(true)
.then(data => {
console.log(data);
return f(false);
})
.then(() => {
console.log('我永远不会被输出');
})
.then(() => {
})
.catch(e => {
console.log(e);
return f(false) ;
});
finally
不论成功还是失败 finally中的内容一定会执行
f(true)
.then(data => {
console.log(data);
return f(false);
})
.catch(e => {
console.log(e);
return f(false);
})
.finally(() => {
console.log(100);
});
promise三种状态
pending 进行中
fulfilled 成功
rejected 失败
状态的改变不可逆:
pending可以到fulfilled或者rejected
Promise.all方法可以把多个promise实例 包装成一个新的promise实例
Promise.all([ promise1, promise2 ]) : Promise
模拟需要多个请求的数据 才能进行下一步操作的情况
function getData1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第一条数据加载成功');
resolve('data1');
}, 1000);
});
}
function getData2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第二条数据加载成功');
resolve('data2');
}, 1000);
});
}
function getData3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第三条数据加载成功');
resolve('data3');
}, 1000);
});
}
function getData4() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第四条数据加载成功');
resolve('data4');
}, 2000);
});
}
// 所有数据都成功,则总决议成功,并返回所有成功提示
let p = Promise.all([getData1(),getData2(),getData3(),getData4()]);
p.then(arr => {
console.log(arr);
});
一条数据失败,则总决议失败,并返回错误信息
function getData1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第一条数据加载成功');
resolve('data1');
}, 1000);
});
}
function getData2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第二条数据加载成功');
resolve('data2');
}, 1000);
});
}
function getData3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第三条数据加载成功');
resolve('data3');
}, 1000);
});
}
function getData4() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('data4 err');
}, 500);
});
}
// 一条数据失败,则总决议失败,并返回错误信息
let p = Promise.all([getData1(),getData2(),getData3(),getData4()]);
p.then(arr => {
console.log(arr);
},e=>{
console.log(e);
});
空数组直接决议为成功
function getData1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第一条数据加载成功');
resolve('data1');
}, 1000);
});
}
function getData2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第二条数据加载成功');
resolve('data2');
}, 1000);
});
}
function getData3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第三条数据加载成功');
resolve('data3');
}, 1000);
});
}
function getData4() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('data4 err');
}, 500);
});
}
// 空数组直接决议为成功
let p = Promise.all([]);
p.then(() => {
console.log('null');
},e=>{
console.log(e);
});
promise.race
只要有一个决议为成功或者失败,就会返回
function getData1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第一条数据加载成功');
reject('err');
}, 500);
});
}
function getData2() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第二条数据加载成功');
resolve('data2');
}, 1000);
});
}
function getData3() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('第三条数据加载成功');
resolve('data3');
}, 1000);
});
}
let p = Promise.race([getData1(),getData2(),getData3()]);
p.then(data => {
console.log(data);
}, e => {
console.log(e);
})
空数组会被挂起
let p = Promise.race([]);
Promise.resolve() 和 Promise.reject()
常用来生成已经被决议为失败或者成功的promise实例
Promise.resolve传递一个普通的值
决议成功并把值传递过去
let p1 = new Promise(resolve => {
resolve('成功!');
});
let p2 = Promise.resolve('成功!');
Promise.resolve传递一个promise实例
let poruomiesi = new Promise(resolve => {
resolve('耶!')
});
// 直接返回传递进去的promise
let p = Promise.resolve(poruomiesi);
p.then(data => void console.log(data));
console.log(p === poruomiesi);
Promise.resolve传递一个thenable
如果传递的是个thenable
let obj = {
then(cb) {
console.log('我被执行了');
cb('哼!');
},
oth() {
console.log('我被抛弃了');
}
}
// 立即执行then方法
Promise.resolve(obj).then(data => {
console.log(data);
});
Promise.reject
直接决议为失败,不做处理
Promise.reject({ then() { console.log(1) } })
.then(() => {
console.log('我不会被执行');
}, e => {
console.log(e);
});
异步任务总是在同步任务之后执行
把同步的任务转成异步任务
function createAsyncTask(syncTask) {
return Promise.resolve(syncTask).then(syncTask => syncTask());
}
createAsyncTask(() => {
console.log('我变成了异步任务!!!');
return 1 + 1;
}).then(res => {
console.log(res);
});
console.log('我是同步任务!');
要求:多张图片加载完之后才能进行统一展示
const loadImg = src => {
return new Promise((resolve, reject) => {
const img = new Image();
img.src = src;
img.onload=()=>{
resolve(img);
};
img.onerror=(e)=>{
reject(e);
};
// img.onload = void resolve(img);
// img.onerror = void reject('加载失败');
});
};
const imgs = [
'http://img1.sycdn.imooc.com\/climg/5b16558d00011ed506000338.jpg',
'http://img1.sycdn.imooc.com\/climg/5b165603000146ca06000338.jpg',
'http://img1.sycdn.imooc.com//climg/5b1656140001c89906000338.jpg'
];
// map遍历数组中的每一项
Promise.all(imgs.map(src => loadImg(src))).then(arr => {
console.log(arr);
arr.forEach((img)=>{
document.body.appendChild(img);
});
});
// map遍历数组中的每一项(与上面相同作用,上面是简写)
// map进行循环,每循环一次就将src作为参数传递进来
// const promises=imgs.map(src =>{
// return loadImg(src);
// });
// Promise.all(promises).then(arr => {
// console.log(arr);
// arr.forEach((img)=>{
// document.body.appendChild(img);
// });
// }).catch((e)=>{
// console.log(e);
// });
来源:https://www.cnblogs.com/chenyingying0/p/12158599.html