promise在Node.js中还是比较常见的,本文主要总结三个常用的promise使用案例。
目录
一、promise 请求超时处理
需求:在微服务中发送一个请求,如果三秒钟还没有收到结果,我们就认为失败。
这里面是使用的是Promise.race。
Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。并行执行
const p = Promise.race([p1, p2, p3]);
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
const p = Promise.race([
getUrl('/resource-that-may-take-a-while'),
new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 5000)
})
]);
p.then(console.log)
.catch(console.error);
二、promise 三次重试
需求:用promise实现一个可以指定重试次数的方法,如果重试次数等于指定的重试测试时,还没有成功,则认为失败。
var execCount = 3;
var getData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
execCount--;
console.error("execCount", execCount);
if (execCount < 0) {
resolve("success");
} else {
reject("error");
}
}, 2000);
});
}
function retryData(getData, times, delay) {
return new Promise((resolve, reject) => {
function attempt() {
getData().then(resolve).catch((erro) => {
console.log(`还有 ${times} 次尝试`);
if (0 == times) {
reject(erro);
} else {
times--;
setTimeout(() => {
attempt();
}, delay * 1000);
}
})
}
attempt();
})
}
retryData(getData, 3, 3).then((res) => {
console.error("执行成功", res);
}).catch((err) => {
console.error(err)
})
execCount 2
还有 3 次尝试
execCount 1
还有 2 次尝试
execCount 0
还有 1 次尝试
execCount -1
执行成功 success
三、promise并发请求并控制请求数目
有 n 个图片资源的 url,已经存储在数组 urls 中(即urls = [‘http://example.com/1.jpg’, …., ‘http://example.com/8.jpg’]),而且已经有一个函数 function loadImg,输入一个 url 链接,返回一个 Promise,该 Promise 在图片下载完成的时候 resolve,下载失败则 reject。
但是我们要求,任意时刻,同时下载的链接数量不可以超过 3 个。
var urls = [1, 2, 3, 4, 5, 6, 7, 8, 9];
function loadImg(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`第 ${url} 张图片加载完成`);
resolve("success");
}, 2 * 1000);
})
};
// 计数器
var count = 0;
// 全局锁
var lock = [];
var l = urls.length;
// 阻塞函数
function block() {
let _resolve;
return new Promise((resolve, reject) => {
_resolve = resolve;
// resolve不执行,将其推入lock数组;
lock.push(_resolve);
});
}
// 叫号机
function next() {
lock.length && lock.shift()();
}
async function reuqest() {
if (count >= 3) {
//超过限制利用await和promise进行阻塞;
await block();
}
if (urls.length > 0) {
console.log(count);
count++
await loadImg(urls.shift());
count--;
next();
}
}
for (let i = 0; i < l; i++) {
reuqest();
}
这里面的思想 我们主要使用async和await 来形成阻塞函数,当我们的请求书大于3个的时候,我们把promise中的resolve保存到数组里面,先不执行。当有图片加载出来后,我们在继续执行