Javascript Promise 一经推出就变得非常流行。Javascript Promise 主要用于处理异步任务。在本文中,我们将通过示例深入探讨 Promise。
Promise 状态:
Javascript Promise 只能有一种状态:Rejected或Fullfilled。
处于履行或拒绝状态的承诺称为已解决的承诺。
Example#1 resolved状态的 Promise
// Asnc function always return Promsie with resolve or resolve state
async function getMyName(){
return "Vijendra Rana"
}
//OR
function getMyName(){
return new Promise((resolve)=>{
resolve("Vijendra Rana")
})
}
//or
function getMyName(){
return Promise.resolve("Vijendra Rana")
}
Example#2 rejected状态的 Promise
// Asnc function always return Promsie with resolve or resolve state
async function getMyName(){
//Throw here return Promise with rejected state with reason
throw Error("Name not found")
}
//OR
function getMyName(){
return new Promise((_,reject)=>{
reject(Error("Name not found"))
})
}
//or
function getMyName(){
return Promise.resolve(Error("Name not found"))
}
//Error - when promise rejected, provide proper reason using Error
Example#3 从resolved的 Promise 中获取响应 - 通过使用 then() 链方法
getMyName().then(res =>{
console.log("------",res)
})
Example#4 promise rejected后 catch()获取错误信息
getMyName().then(res =>{
console.log("------",res)
})
.catch(err =>{
//log the reasons
})
Example#5 在 then() 中,我们可以添加rejected和resolved处理方法
//Reject Hanndler
async function getAllNames(id) {
if (id) {
return ["a", "b", "c"];
} else {
throw new Error("id is undefined");
}
}
//every Promise has resolve and reject hander
const namePromise = getAllNames(12);
// namePromise
// .then((res) => {
// console.log(res);
// })
// .catch((err) => {
// console.warn(err);
// });
console.log(typeof namePromise);
namePromise.then(
() => {
console.log("Resolved");
},
() => {
console.log("Unresolved");
}
);
Example#6 finally() 不管rejected还是resolved都会执行
//finally to clean up
async function getMovies(id) {
if (id) {
return ["1", "2", "3"];
} else {
throw new Error("Id req");
}
}
getMovies(12)
.then((res) => {
if (!res) {
throw Error("Unsuccessful attempt");
} else {
console.log("data", res);
}
})
.catch((err) => {
console.log("error-->", err);
throw new Error("....");
})
.finally(() => {
console.log("more clean up work");
});
Example#7 在then主动抛出错误,但是不是被cathch捕获
//Promise to reject
async function getMovies(id) {
if (id) {
return ["1", "2"];
} else {
return [];
}
}
getMovies().then((res) => {
if (res.length === 0) {
return Promise.reject(new Error("unsuccessful response"));
}
}).catch((err) =>{
console.warn('---!!!!',err);
});
Example#8 使用 Promise 构造函数创建 Promise。
//Promise Constructor
// const promise = new Promise((resolve, reject) => {
// // do some async operation then return promise with resolved state
// setTimeout(() => {
// resolve();
// }, [1000]);
// });
//refactor to sleep
// function sleep(ms) {
// return new Promise((resolve) => {
// // do some async operation then return promise with resolved state
// setTimeout(() => {
// resolve();
// }, [ms]);
// });
// }
//further refactor
function sleep(ms) {
return new Promise((resolve) => {
// do some async operation then return promise with resolved state
setTimeout(resolve, ms);
});
}
//resolve invoked jsut after constructor called not an asynchronous call so if
function Rejectsleep(ms) {
return new Promise((resolve) => {
throw Error("+++++");
setTimeout(resolve, ms);// This line will not be reachable
});
}
sleep(1000)
.then(() => {
console.log("Resolved");
})
.catch((err) => {
console.log("Rejected from resolved promise");
});
Rejectsleep(1000)
.then(() => {
console.log("Resolved");
})
.catch((err) => {
console.log("Rejected from resolved promise");
});
Example#9 回调函数使用 Promise
//convert call back to promise
//read file from fs lib, Node api use callback heavily
// import { readFile } from "fs";
const fs = require("fs");
//this is callback based
// fs.readFile(__filename, "utf-8", (error, contents) => {
// if (error) {
// console.error(error);
// } else {
// console.log(contents);
// }
// });
//convert to Promise based app
function readFile(path, encoding) {
return new Promise((resolve, reject) => {
fs.readFile(path, encoding, (error, contents) => {
if (error) {
reject(error);
} else {
resolve(contents);
}
});
});
}
readFile(__filename, "utf8").then(
(contents) => {
console.log(contents);
},
(error) => {
console.error(error);
}
);
Example#10 Promise.race() - 获得最快的结果,当有一个执行完成就不再执行
//Promise.race()
//examplep-1
function resolveAfter(ms, value) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(value);
}, [ms]);
});
}
// const pA = resolveAfter(1000, "A");
// const pB = resolveAfter(2000, "B");
// const PResult = Promise.race([pA, pB]);
// PResult.then((val) => {
// console.log(val);
// });
//Least use of Race method but in one case
function timeout(ms, promise) {
let timeoutId;
const timeoutPromise = new Promise((_, reject) => {
timeoutId = setTimeout(() => {
reject(Error(`Operation timed out after ${ms}`));
}, ms);
});
return Promise.race([promise, timeoutPromise]).finally(() => {
clearTimeout(timeoutId);
});
}
const promise = resolveAfter(1000, "Promise A");
timeout(5000, promise).then(
(value) => {
console.log(value);
},
(error) => {
console.error(error);
}
);
Example#11 Promise.all() - 当所有 API 并行调用时获取所有 Promise
//Promise.all
async function getMovieTitle(id){
return "Iron Man"
}
async function getMovieId(dir, actor){
return 1
}
// getMovieId("Rachel","RJD").then((res) =>{
// if(res){
// getMovieTitle(res).then((t) =>{
// console.log('++++',t);
// })
// }
// })
//If both are independent call then call Parallely
const promsies = Promise.all([
getMovieId("Rachel","RJD"),
getMovieTitle(1)
])
// console.log('Fullfilled Promsie',promsies);
promsies.then(([id,title]) =>{
// const id = res[0]
// const title = res[1]
console.log('Id',id, 'Title',title);
}).catch(err =>{
console.log(err);
}).finally(() =>{
//do some clean up work
})
//in order Promise to be fullfilled , all promise must be fullfilled
Example#12 如果 Promsie.all() 中的任何一个 Promise 失败,则不会返回一个带有拒绝状态的 Promsie。可以使用 Promsie.allSettled()
//Promsie.allSettled
async function getMovieTitle(id) {
throw Error("Something Wrong!!");
}
async function getMovieId(dir, actor) {
return 1;
}
//Promise.allSettled always return settlled promise
Promise.allSettled([getMovieId("Rachel", "RJD"), getMovieTitle(1)]).then(
([id, title]) => {
if (id.status === "fulfilled") {
console.log(id.value);
}
if (title.status === "fulfilled") {
console.log(title.value);
}
}
);
Example#13 Promise.any() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。
//Promsie.any() to make more resilinet in api down time
var promises = [
Promise.reject(Error("Fail#1")),
Promise.reject(Error("Fail#2")),
// Promise.resolve(2),
];
// Promsie.any return fullfilled promise if any Promise is fullfilled
Promise.any(promises).then(
(value) => {
console.log("fullfilled ", value);
},
(error) => {
console.warn(error.errors);
}
);
Example#14 Async/Await - 我们可以使用 JS 中带有 async/await 关键字的写可读性更好的代码。
//Async/Await
function getMovies() {
return new Promise((resolve, reject) => {
resolve(["a", "b", "c"]);
// reject(Error("Erorr Occured"));
});
}
function getMovies2() {
return new Promise((resolve) => {
resolve(["a1", "b1", "c1"]);
});
}
async function main() {
try {
//it is a sequential api call
// const movies = await getMovies();
// const movies2 = await getMovies2();
//parrallel
const [movies, movies2] = await Promise.all([
await getMovies(),
await getMovies2(),
]);
console.log("+++++", movies, movies2);
} catch (error) {
console.log("Some error occured");
}
}
main();
我希望它能帮助理解和编写 JS 中基于 Promise 的代码。