Skip to content

Commit

Permalink
Rename internal cache helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
gaearon committed Dec 9, 2020
1 parent 6a4b12b commit dd40435
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 138 deletions.
85 changes: 45 additions & 40 deletions packages/react-fetch/src/ReactFetchBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,63 +15,63 @@ const Pending = 0;
const Resolved = 1;
const Rejected = 2;

type PendingResult = {|
type PendingRecord = {|
status: 0,
value: Wakeable,
|};

type ResolvedResult = {|
type ResolvedRecord = {|
status: 1,
value: mixed,
|};

type RejectedResult = {|
type RejectedRecord = {|
status: 2,
value: mixed,
|};

type Result = PendingResult | ResolvedResult | RejectedResult;
type Record = PendingRecord | ResolvedRecord | RejectedRecord;

// TODO: this is a browser-only version. Add a separate Node entry point.
const nativeFetch = window.fetch;

function getResultMap(): Map<string, Result> {
return unstable_getCacheForType(createResultMap);
function getRecordMap(): Map<string, Record> {
return unstable_getCacheForType(createRecordMap);
}

function createResultMap(): Map<string, Result> {
function createRecordMap(): Map<string, Record> {
return new Map();
}

function toResult(thenable): Result {
const result: Result = {
function createRecordFromThenable(thenable): Record {
const record: Record = {
status: Pending,
value: thenable,
};
thenable.then(
value => {
if (result.status === Pending) {
const resolvedResult = ((result: any): ResolvedResult);
resolvedResult.status = Resolved;
resolvedResult.value = value;
if (record.status === Pending) {
const resolvedRecord = ((record: any): ResolvedRecord);
resolvedRecord.status = Resolved;
resolvedRecord.value = value;
}
},
err => {
if (result.status === Pending) {
const rejectedResult = ((result: any): RejectedResult);
rejectedResult.status = Rejected;
rejectedResult.value = err;
if (record.status === Pending) {
const rejectedRecord = ((record: any): RejectedRecord);
rejectedRecord.status = Rejected;
rejectedRecord.value = err;
}
},
);
return result;
return record;
}

function readResult(result: Result) {
if (result.status === Resolved) {
return result.value;
function readRecordValue(record: Record) {
if (record.status === Resolved) {
return record.value;
} else {
throw result.value;
throw record.value;
}
}

Expand All @@ -94,32 +94,37 @@ function Response(nativeResponse) {
Response.prototype = {
constructor: Response,
arrayBuffer() {
return readResult(
return readRecordValue(
this._arrayBuffer ||
(this._arrayBuffer = toResult(this._response.arrayBuffer())),
(this._arrayBuffer = createRecordFromThenable(
this._response.arrayBuffer(),
)),
);
},
blob() {
return readResult(
this._blob || (this._blob = toResult(this._response.blob())),
return readRecordValue(
this._blob ||
(this._blob = createRecordFromThenable(this._response.blob())),
);
},
json() {
return readResult(
this._json || (this._json = toResult(this._response.json())),
return readRecordValue(
this._json ||
(this._json = createRecordFromThenable(this._response.json())),
);
},
text() {
return readResult(
this._text || (this._text = toResult(this._response.text())),
return readRecordValue(
this._text ||
(this._text = createRecordFromThenable(this._response.text())),
);
},
};

function preloadResult(url: string, options: mixed): Result {
const map = getResultMap();
let entry = map.get(url);
if (!entry) {
function preloadRecord(url: string, options: mixed): Record {
const map = getRecordMap();
let record = map.get(url);
if (!record) {
if (options) {
if (options.method || options.body || options.signal) {
// TODO: wire up our own cancellation mechanism.
Expand All @@ -128,20 +133,20 @@ function preloadResult(url: string, options: mixed): Result {
}
}
const thenable = nativeFetch(url, options);
entry = toResult(thenable);
map.set(url, entry);
record = createRecordFromThenable(thenable);
map.set(url, record);
}
return entry;
return record;
}

export function preload(url: string, options: mixed): void {
preloadResult(url, options);
preloadRecord(url, options);
// Don't return anything.
}

export function fetch(url: string, options: mixed): Object {
const result = preloadResult(url, options);
const nativeResponse = (readResult(result): any);
const record = preloadRecord(url, options);
const nativeResponse = (readRecordValue(record): any);
if (nativeResponse._reactResponse) {
return nativeResponse._reactResponse;
} else {
Expand Down
83 changes: 42 additions & 41 deletions packages/react-fetch/src/ReactFetchNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,36 +57,36 @@ const Pending = 0;
const Resolved = 1;
const Rejected = 2;

type PendingResult = {|
type PendingRecord = {|
status: 0,
value: Wakeable,
|};

type ResolvedResult<V> = {|
type ResolvedRecord<V> = {|
status: 1,
value: V,
|};

type RejectedResult = {|
type RejectedRecord = {|
status: 2,
value: mixed,
|};

type Result<V> = PendingResult | ResolvedResult<V> | RejectedResult;
type Record<V> = PendingRecord | ResolvedRecord<V> | RejectedRecord;

function getResultMap(): Map<string, Result<FetchResponse>> {
return unstable_getCacheForType(createResultMap);
function getRecordMap(): Map<string, Record<FetchResponse>> {
return unstable_getCacheForType(createRecordMap);
}

function createResultMap(): Map<string, Result<FetchResponse>> {
function createRecordMap(): Map<string, Record<FetchResponse>> {
return new Map();
}

function readResult<T>(result: Result<T>): T {
if (result.status === Resolved) {
return result.value;
function readRecordValue<T>(record: Record<T>): T {
if (record.status === Resolved) {
return record.value;
} else {
throw result.value;
throw record.value;
}
}

Expand All @@ -111,7 +111,7 @@ function Response(nativeResponse) {
cb();
}
}
const result: PendingResult = (this._result = {
const bufferRecord: PendingRecord = (this._bufferRecord = {
status: Pending,
value: {
then(cb) {
Expand All @@ -122,18 +122,18 @@ function Response(nativeResponse) {
const data = [];
nativeResponse.on('data', chunk => data.push(chunk));
nativeResponse.on('end', () => {
if (result.status === Pending) {
const resolvedResult = ((result: any): ResolvedResult<Buffer>);
resolvedResult.status = Resolved;
resolvedResult.value = Buffer.concat(data);
if (bufferRecord.status === Pending) {
const resolvedRecord = ((bufferRecord: any): ResolvedRecord<Buffer>);
resolvedRecord.status = Resolved;
resolvedRecord.value = Buffer.concat(data);
wake();
}
});
nativeResponse.on('error', err => {
if (result.status === Pending) {
const rejectedResult = ((result: any): RejectedResult);
rejectedResult.status = Rejected;
rejectedResult.value = err;
if (bufferRecord.status === Pending) {
const rejectedRecord = ((bufferRecord: any): RejectedRecord);
rejectedRecord.status = Rejected;
rejectedRecord.value = err;
wake();
}
});
Expand All @@ -142,7 +142,7 @@ function Response(nativeResponse) {
Response.prototype = {
constructor: Response,
arrayBuffer() {
const buffer = readResult(this._result);
const buffer = readRecordValue(this._bufferRecord);
return buffer;
},
blob() {
Expand All @@ -153,7 +153,7 @@ Response.prototype = {
if (this._json !== null) {
return this._json;
}
const buffer = readResult(this._result);
const buffer = readRecordValue(this._bufferRecord);
const json = JSON.parse(buffer.toString());
this._json = json;
return json;
Expand All @@ -162,17 +162,17 @@ Response.prototype = {
if (this._text !== null) {
return this._text;
}
const buffer = readResult(this._result);
const buffer = readRecordValue(this._bufferRecord);
const text = buffer.toString();
this._text = text;
return text;
},
};

function preloadResult(url: string, options: mixed): Result<FetchResponse> {
const map = getResultMap();
let entry = map.get(url);
if (!entry) {
function preloadRecord(url: string, options: mixed): Record<FetchResponse> {
const map = getRecordMap();
let record = map.get(url);
if (!record) {
if (options) {
if (options.method || options.body || options.signal) {
// TODO: wire up our own cancellation mechanism.
Expand All @@ -193,41 +193,42 @@ function preloadResult(url: string, options: mixed): Result<FetchResponse> {
cb();
}
};
const result: Result<FetchResponse> = (entry = {
const newRecord: Record<FetchResponse> = (record = {
status: Pending,
value: wakeable,
});
nodeFetch(
url,
options,
response => {
if (result.status === Pending) {
const resolvedResult = ((result: any): ResolvedResult<FetchResponse>);
resolvedResult.status = Resolved;
resolvedResult.value = response;
if (newRecord.status === Pending) {
const resolvedRecord = ((newRecord: any): ResolvedRecord<FetchResponse>);
resolvedRecord.status = Resolved;
resolvedRecord.value = response;
wake();
}
},
err => {
if (result.status === Pending) {
const rejectedResult = ((result: any): RejectedResult);
rejectedResult.status = Rejected;
rejectedResult.value = err;
if (newRecord.status === Pending) {
const rejectedRecord = ((newRecord: any): RejectedRecord);
rejectedRecord.status = Rejected;
rejectedRecord.value = err;
wake();
}
},
);
map.set(url, entry);
map.set(url, record);
}
return entry;
return record;
}

export function preload(url: string, options: mixed): void {
preloadResult(url, options);
preloadRecord(url, options);
// Don't return anything.
}

export function fetch(url: string, options: mixed): FetchResponse {
const result = preloadResult(url, options);
return readResult(result);
const record = preloadRecord(url, options);
const response = readRecordValue(record);
return response;
}
Loading

0 comments on commit dd40435

Please sign in to comment.