Promise.all() and Promise.allSettled()
Promise.all
andPromise.allSettled
are both methods for handling multiple concurrent Promises, but they differ in how they handle successful and failed Promises.
Promise.all
Promise.all
accepts an array of Promise as parameters.When all Promises are resolved,
Promise.all
is also resolved, and the return value is an array containing the results of all successful Promises.If any Promise fails (rejected),
Promise.all
will also immediately fail (rejected), and the return value is the reason for the first failed Promise.This means that if you use
Promise.all
, if one Promise fails, the entirePromise.all
will fail immediately before all Promises have completed. Therefore,Promise.all
is more suitable for scenarios where all Promises need to succeed.
1
2
3
4
5
6
7javascriptCopy codePromise.all([promise1, promise2, promise3])
.then((results) => {
// All promises fulfilled successfully
})
.catch((error) => {
// At least one promise was rejected
});
Promise.allSettled
Promise.allSettled
also accepts an array of Promise as parameters.Promise.allSettled
will wait for all Promises to complete, regardless of whether each Promise succeeds or fails.Promise.allSettled
succeeds (resolved) when all Promises are completed (regardless of success or failure), and the return value is an array containing the status of all Promise (success or failure). Each element in the array is an object that contains astatus
property (with a value of"fulfilled"
or"rejected"
) and avalue
(the result on success) orreason
(on failure time reason) attribute.- This means that if you use
Promise.allSettled
, even if one or more Promises fail, the entirePromise.allSettled
will still succeed and return the final status of all Promises. Therefore,Promise.allSettled
is more suitable for scenarios where you need to know the final status of all Promises, not just the success status.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'Error'));
const promise3 = Promise.resolve(5);
Promise.all([promise1, promise2, promise3])
.then(console.log)
.catch(console.error); // Output: Error (because promise2 was rejected)
Promise.allSettled([promise1, promise2, promise3])
.then(console.log)
.catch(console.error);
// Output: [
// { status: "fulfilled", value: 3 },
// { status: "rejected", reason: "Error"
Example: Music Player
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
interface ArtistResults {
status: "fulfilled" | "rejected";
value: IBanner;
}
interface AlbumListResults {
status: "fulfilled" | "rejected";
value: IAlbumList;
}
function getRandomInt() {
return Math.floor(Math.random() * 10);
}
async function getArtist(areaCode: AreaCode) {
const randomInteger = Math.floor(Math.random() * 100000) + 1;
const artistRes = await fetch(
`${
process.env.NEXT_PUBLIC_SERVER_ADDRESS
}/artist/list?area=${areaCode}&limit=1&offset=${getRandomInt()}×tamp=${
Date.now() - randomInteger
}`
);
const artistArray = await artistRes.json();
const artist = artistArray.artists[0];
const artistSongRes = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_ADDRESS}/artists?id=${
artist.id
}&limit=6&order=time×tamp=${Date.now() - randomInteger}`
);
const artistDetails = await artistSongRes.json();
const artistSongsDetails = artistDetails.hotSongs.slice(0, 6) as IAlbumSong[];
const artistSongs = artistSongsDetails.map((song) => {
return {
name: song.name,
id: song.id,
image: song.al.picUrl,
};
});
const colorRes = await fetch(
`${
process.env.NEXT_PUBLIC_CLIENT_ADDRESS
}/api/colorExtract?imageUrl=${convertToHttps(artist.picUrl)}`
);
const color = await colorRes.json();
const banner: IBanner = {
artistId: artist.id,
artistName: artist.name,
artistCover: convertToHttps(artist.picUrl) as string,
artistAreaCode: areaCode,
artistAlias: artist.alias,
bgColor: color.dominantColor,
artistSongs: artistSongs,
};
return banner;
}
export async function fetchArtistsInfo(areas: AreaCode[]) {
try {
const promises = areas.map((area: AreaCode) => getArtist(area));
const results = await Promise.allSettled(promises);
const filteredResults = results.filter(
(result) => result.status === "fulfilled"
) as ArtistResults[];
const resultAlbums = filteredResults.map((results: ArtistResults) => {
return results.value;
});
return resultAlbums;
} catch (error) {
console.error("Error fetching data:", error);
throw error;
}
}
async function getAlbumLists(area: AlbumArea) {
const albumRes = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_ADDRESS}/album/list/style?area=${area}&limit=13`
);
const rawAlbumLists = await albumRes.json();
const albumLists = {
...rawAlbumLists,
title: albumAreaMapper(area),
path: `album/list/style?area=${area}&`,
};
return albumLists;
}
export async function fetchAlbumListInfo(albumAreas: AlbumArea[]) {
try {
const promises = albumAreas.map((albumArea: AlbumArea) =>
getAlbumLists(albumArea)
);
const results = await Promise.allSettled(promises);
const filteredResults = results.filter(
(result) => result.status === "fulfilled"
) as AlbumListResults[];
const resultAlbumLists = filteredResults.map(
(results: AlbumListResults) => {
return results.value;
}
);
return resultAlbumLists;
} catch (error) {
console.error("Error in fetching area album lists data:", error);
throw error;
}
}
export async function getPlaylistList(playListType: "/highquality" | "") {
const topPlaylistListResponse = await fetch(
`${process.env.NEXT_PUBLIC_SERVER_ADDRESS}/top/playlist${playListType}?limit=13`
);
const rawTopLists = await topPlaylistListResponse.json();
const topPlaylistList = await playlistsGroupTranslator(rawTopLists);
return { ...topPlaylistList, path: `top/playlist${playListType}?` };
}