Skip to content

Commit ac7e089

Browse files
committed
minor changes
1 parent 033d5be commit ac7e089

File tree

1 file changed

+66
-51
lines changed

1 file changed

+66
-51
lines changed

packages/expo-resource-fetcher/src/handlers.ts

Lines changed: 66 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ export interface ActiveDownload {
2828
uri: string;
2929
fileUri: string;
3030
cacheFileUri: string;
31-
/** Resolves the pending Promise<string | null> inside the fetch() loop. */
31+
// settle and reject are the resolve/reject of the Promise returned by handleRemote.
32+
// They are stored here so that cancel() and resume() in the fetcher class can
33+
// unblock the fetch() loop from outside the download flow.
3234
settle: (path: string | null) => void;
33-
/** Rejects the pending Promise inside the fetch() loop. */
3435
reject: (error: unknown) => void;
3536
}
3637

@@ -61,7 +62,9 @@ export async function handleAsset(
6162
const uri = asset.uri;
6263

6364
if (uri.startsWith('http')) {
64-
// Dev mode: asset served from Metro dev server
65+
// Dev mode: asset served from Metro dev server.
66+
// uri is the resolved HTTP URL; source is the original require() number the
67+
// user holds, so it must be used as the downloads map key for pause/cancel to work.
6568
return handleRemote(uri, source, progressCallback, downloads);
6669
}
6770

@@ -81,7 +84,11 @@ export async function handleAsset(
8184
return ResourceFetcherUtils.removeFilePrefix(fileUriWithType);
8285
}
8386

84-
export function handleRemote(
87+
// uri and source are separate parameters because for asset sources (dev mode),
88+
// source is the require() number the user holds (used as the downloads map key),
89+
// while uri is the resolved HTTP URL needed for the actual download.
90+
// For plain remote strings they are the same value.
91+
export async function handleRemote(
8592
uri: string,
8693
source: ResourceSource,
8794
progressCallback: (progress: number) => void,
@@ -94,57 +101,58 @@ export function handleRemote(
94101
);
95102
}
96103

97-
let settle!: (path: string | null) => void;
98-
let reject!: (error: unknown) => void;
104+
const filename = ResourceFetcherUtils.getFilenameFromUri(uri);
105+
const fileUri = `${RNEDirectory}${filename}`;
106+
const cacheFileUri = `${cacheDirectory}${filename}`;
99107

108+
if (await ResourceFetcherUtils.checkFileExists(fileUri)) {
109+
return ResourceFetcherUtils.removeFilePrefix(fileUri);
110+
}
111+
112+
await ResourceFetcherUtils.createDirectoryIfNoExists();
113+
114+
// We need a Promise whose resolution can be triggered from outside this function —
115+
// by cancel() or resume() in the fetcher class. A plain async function can't do that,
116+
// so we create the Promise manually and store settle/reject in the downloads map.
117+
let settle: (path: string | null) => void = () => {};
118+
let reject: (error: unknown) => void = () => {};
100119
const promise = new Promise<string | null>((res, rej) => {
101120
settle = res;
102121
reject = rej;
103122
});
104123

105-
void (async () => {
106-
const filename = ResourceFetcherUtils.getFilenameFromUri(uri);
107-
const fileUri = `${RNEDirectory}${filename}`;
108-
const cacheFileUri = `${cacheDirectory}${filename}`;
109-
110-
try {
111-
if (await ResourceFetcherUtils.checkFileExists(fileUri)) {
112-
settle(ResourceFetcherUtils.removeFilePrefix(fileUri));
113-
return;
124+
const downloadResumable = createDownloadResumable(
125+
uri,
126+
cacheFileUri,
127+
{ sessionType: FileSystemSessionType.BACKGROUND },
128+
({
129+
totalBytesWritten,
130+
totalBytesExpectedToWrite,
131+
}: {
132+
totalBytesWritten: number;
133+
totalBytesExpectedToWrite: number;
134+
}) => {
135+
if (totalBytesExpectedToWrite === -1) {
136+
progressCallback(0);
137+
} else {
138+
progressCallback(totalBytesWritten / totalBytesExpectedToWrite);
114139
}
140+
}
141+
);
142+
143+
downloads.set(source, {
144+
downloadResumable,
145+
status: DownloadStatus.ONGOING,
146+
uri,
147+
fileUri,
148+
cacheFileUri,
149+
settle,
150+
reject,
151+
});
115152

116-
await ResourceFetcherUtils.createDirectoryIfNoExists();
117-
118-
const downloadResumable = createDownloadResumable(
119-
uri,
120-
cacheFileUri,
121-
{ sessionType: FileSystemSessionType.BACKGROUND },
122-
({
123-
totalBytesWritten,
124-
totalBytesExpectedToWrite,
125-
}: {
126-
totalBytesWritten: number;
127-
totalBytesExpectedToWrite: number;
128-
}) => {
129-
if (totalBytesExpectedToWrite === -1) {
130-
progressCallback(0);
131-
} else {
132-
progressCallback(totalBytesWritten / totalBytesExpectedToWrite);
133-
}
134-
}
135-
);
136-
137-
downloads.set(source, {
138-
downloadResumable,
139-
status: DownloadStatus.ONGOING,
140-
uri,
141-
fileUri,
142-
cacheFileUri,
143-
settle,
144-
reject,
145-
});
146-
147-
const result = await downloadResumable.downloadAsync();
153+
downloadResumable
154+
.downloadAsync()
155+
.then(async (result) => {
148156
const dl = downloads.get(source);
149157
// If paused or canceled during the download, settle/reject will be called
150158
// externally by resume() or cancel() — do nothing here.
@@ -165,15 +173,22 @@ export function handleRemote(
165173
return;
166174
}
167175

168-
await moveAsync({ from: cacheFileUri, to: fileUri });
176+
try {
177+
await moveAsync({ from: cacheFileUri, to: fileUri });
178+
} catch (error) {
179+
downloads.delete(source);
180+
reject(error);
181+
return;
182+
}
183+
169184
downloads.delete(source);
170185
ResourceFetcherUtils.triggerHuggingFaceDownloadCounter(uri);
171186
settle(ResourceFetcherUtils.removeFilePrefix(fileUri));
172-
} catch (error) {
187+
})
188+
.catch((error) => {
173189
downloads.delete(source);
174190
reject(error);
175-
}
176-
})();
191+
});
177192

178193
return promise;
179194
}

0 commit comments

Comments
 (0)