Skip to content

Commit 41cc568

Browse files
authored
chore(PouchDB-find): purified promise flow (#8860)
* refactor internal callback-flow to promises * remove unused utils * add JSDoc with usage example to `resolveToCallback`
1 parent 08649d9 commit 41cc568

File tree

4 files changed

+67
-166
lines changed

4 files changed

+67
-166
lines changed

packages/node_modules/pouchdb-find/src/adapters/http/index.js

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,70 +19,50 @@ async function dbFetch(db, path, opts) {
1919
return json;
2020
}
2121

22-
function createIndex(db, requestDef, callback) {
23-
dbFetch(db, '_index', {
22+
async function createIndex(db, requestDef) {
23+
return await dbFetch(db, '_index', {
2424
method: 'POST',
2525
body: massageCreateIndexRequest(requestDef)
26-
})
27-
.then((result) => {
28-
callback(null, result);
29-
})
30-
.catch(callback);
26+
});
3127
}
3228

33-
function find(db, requestDef, callback) {
29+
async function find(db, requestDef) {
3430
validateSelector(requestDef.selector, true);
35-
dbFetch(db, '_find', {
31+
return await dbFetch(db, '_find', {
3632
method: 'POST',
3733
body: requestDef
38-
})
39-
.then((result) => {
40-
callback(null, result);
41-
})
42-
.catch(callback);
34+
});
4335
}
4436

45-
function explain(db, requestDef, callback) {
46-
dbFetch(db, '_explain', {
37+
async function explain(db, requestDef) {
38+
return await dbFetch(db, '_explain', {
4739
method: 'POST',
4840
body: requestDef
49-
})
50-
.then((result) => {
51-
callback(null, result);
52-
})
53-
.catch(callback);
41+
});
5442
}
5543

56-
function getIndexes(db, callback) {
57-
return dbFetch(db, '_index', {
58-
method: 'GET',
59-
})
60-
.then((result) => {
61-
callback(null, result);
62-
})
63-
.catch(callback);
44+
async function getIndexes(db) {
45+
return await dbFetch(db, '_index', {
46+
method: 'GET'
47+
});
6448
}
6549

66-
function deleteIndex(db, indexDef, callback) {
50+
async function deleteIndex(db, indexDef) {
6751
const ddoc = indexDef.ddoc;
6852
const type = indexDef.type || 'json';
6953
const name = indexDef.name;
7054

7155
if (!ddoc) {
72-
return callback(new Error('you must provide an index\'s ddoc'));
56+
throw new Error('you must provide an index\'s ddoc');
7357
}
7458

7559
if (!name) {
76-
return callback(new Error('you must provide an index\'s name'));
60+
throw new Error('you must provide an index\'s name');
7761
}
7862

7963
const url = '_index/' + [ddoc, type, name].map(encodeURIComponent).join('/');
8064

81-
dbFetch(db, url, { method: 'DELETE' })
82-
.then((result) => {
83-
callback(null, result);
84-
})
85-
.catch(callback);
65+
return await dbFetch(db, url, { method: 'DELETE' });
8666
}
8767

8868
export {
Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
1-
import { callbackify } from '../../utils';
21
import createIndex from './create-index';
3-
import {find, explain } from './find';
2+
import { find, explain } from './find';
43
import getIndexes from './get-indexes';
54
import deleteIndex from './delete-index';
65

7-
const createIndexAsCallback = callbackify(createIndex);
8-
const findAsCallback = callbackify(find);
9-
const explainAsCallback = callbackify(explain);
10-
const getIndexesAsCallback = callbackify(getIndexes);
11-
const deleteIndexAsCallback = callbackify(deleteIndex);
12-
136
export {
14-
createIndexAsCallback as createIndex,
15-
findAsCallback as find,
16-
getIndexesAsCallback as getIndexes,
17-
deleteIndexAsCallback as deleteIndex,
18-
explainAsCallback as explain
7+
createIndex,
8+
find,
9+
getIndexes,
10+
deleteIndex,
11+
explain
1912
};
Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,50 @@
1-
import { toPromise, isRemote } from 'pouchdb-utils';
1+
import { isRemote } from 'pouchdb-utils';
2+
import { resolveToCallback } from './utils';
23
import * as http from './adapters/http/index';
34
import * as local from './adapters/local/index';
45

56
const plugin = {};
6-
plugin.createIndex = toPromise(function (requestDef, callback) {
7-
7+
plugin.createIndex = resolveToCallback(async function (requestDef) {
88
if (typeof requestDef !== 'object') {
9-
return callback(new Error('you must provide an index to create'));
9+
throw new Error('you must provide an index to create');
1010
}
1111

1212
const createIndex = isRemote(this) ?
1313
http.createIndex : local.createIndex;
14-
createIndex(this, requestDef, callback);
14+
return createIndex(this, requestDef);
1515
});
1616

17-
plugin.find = toPromise(function (requestDef, callback) {
18-
19-
if (typeof callback === 'undefined') {
20-
callback = requestDef;
21-
requestDef = undefined;
22-
}
23-
17+
plugin.find = resolveToCallback(async function (requestDef) {
2418
if (typeof requestDef !== 'object') {
25-
return callback(new Error('you must provide search parameters to find()'));
19+
throw new Error('you must provide search parameters to find()');
2620
}
2721

2822
const find = isRemote(this) ? http.find : local.find;
29-
find(this, requestDef, callback);
23+
return find(this, requestDef);
3024
});
3125

32-
plugin.explain = toPromise(function (requestDef, callback) {
33-
34-
if (typeof callback === 'undefined') {
35-
callback = requestDef;
36-
requestDef = undefined;
37-
}
38-
26+
plugin.explain = resolveToCallback(async function (requestDef) {
3927
if (typeof requestDef !== 'object') {
40-
return callback(new Error('you must provide search parameters to explain()'));
28+
throw new Error('you must provide search parameters to explain()');
4129
}
4230

4331
const find = isRemote(this) ? http.explain : local.explain;
44-
find(this, requestDef, callback);
32+
return find(this, requestDef);
4533
});
4634

47-
plugin.getIndexes = toPromise(function (callback) {
48-
35+
plugin.getIndexes = resolveToCallback(async function () {
4936
const getIndexes = isRemote(this) ? http.getIndexes : local.getIndexes;
50-
getIndexes(this, callback);
37+
return getIndexes(this);
5138
});
5239

53-
plugin.deleteIndex = toPromise(function (indexDef, callback) {
54-
40+
plugin.deleteIndex = resolveToCallback(async function (indexDef) {
5541
if (typeof indexDef !== 'object') {
56-
return callback(new Error('you must provide an index to delete'));
42+
throw new Error('you must provide an index to delete');
5743
}
5844

5945
const deleteIndex = isRemote(this) ?
6046
http.deleteIndex : local.deleteIndex;
61-
deleteIndex(this, indexDef, callback);
47+
return deleteIndex(this, indexDef);
6248
});
6349

6450
export default plugin;

packages/node_modules/pouchdb-find/src/utils.js

Lines changed: 28 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -4,88 +4,6 @@ import {
44
parseField
55
} from 'pouchdb-selector-core';
66

7-
import { nextTick } from 'pouchdb-utils';
8-
9-
function once(fun) {
10-
let called = false;
11-
return function (...args) {
12-
if (called) {
13-
console.trace();
14-
throw new Error('once called more than once');
15-
} else {
16-
called = true;
17-
fun.apply(this, args);
18-
}
19-
};
20-
}
21-
function toPromise(func) {
22-
//create the function we will be returning
23-
return function (...args) {
24-
const self = this;
25-
const tempCB = (typeof args[args.length - 1] === 'function') ? args.pop() : false;
26-
// if the last argument is a function, assume its a callback
27-
let usedCB;
28-
if (tempCB) {
29-
// if it was a callback, create a new callback which calls it,
30-
// but do so async so we don't trap any errors
31-
usedCB = function (err, resp) {
32-
nextTick(function () {
33-
tempCB(err, resp);
34-
});
35-
};
36-
}
37-
const promise = new Promise(function (fulfill, reject) {
38-
try {
39-
const callback = once(function (err, mesg) {
40-
if (err) {
41-
reject(err);
42-
} else {
43-
fulfill(mesg);
44-
}
45-
});
46-
// create a callback for this invocation
47-
// apply the function in the orig context
48-
args.push(callback);
49-
func.apply(self, args);
50-
} catch (e) {
51-
reject(e);
52-
}
53-
});
54-
// if there is a callback, call it back
55-
if (usedCB) {
56-
promise.then(function (result) {
57-
usedCB(null, result);
58-
}, usedCB);
59-
}
60-
promise.cancel = function () {
61-
return this;
62-
};
63-
return promise;
64-
};
65-
}
66-
67-
function callbackify(fun) {
68-
return function (...args) {
69-
const cb = args.pop();
70-
const promise = fun.apply(this, args);
71-
promisedCallback(promise, cb);
72-
return promise;
73-
};
74-
}
75-
76-
function promisedCallback(promise, callback) {
77-
promise.then(function (res) {
78-
nextTick(function () {
79-
callback(null, res);
80-
});
81-
}, function (reason) {
82-
nextTick(function () {
83-
callback(reason);
84-
});
85-
});
86-
return promise;
87-
}
88-
897
const nativeFlat = (...args) => args.flat(Infinity);
908

919
const polyFlat = (...args) => {
@@ -200,19 +118,43 @@ function uniq(arr) {
200118
return Array.from(new Set(arr));
201119
}
202120

121+
/**
122+
* Callbackifyable wrapper for async functions
123+
*
124+
* @template T, Args
125+
* @param {(...args: Args) => Promise<T>} fun
126+
* @returns {<CBArgs = [...Args, (err: any, value: T) => void], InnerArgs extends Args | CBArgs>(...innerArgs: InnerArgs) => InnerArgs extends CBArgs ? void : Promise<T>}
127+
*
128+
* @example
129+
* const fn = resolveToCallback(async () => { return 42; })
130+
* // with callback:
131+
* fn((err, value) => { ... })
132+
* // with await:
133+
* const value = await fn()
134+
*/
135+
function resolveToCallback(fun) {
136+
return function (...args) {
137+
const maybeCallback = args[args.length - 1];
138+
if (typeof maybeCallback === "function") {
139+
const fulfilled = maybeCallback.bind(null, null);
140+
const rejected = maybeCallback.bind(null);
141+
fun.apply(this, args.slice(0, -1)).then(fulfilled, rejected);
142+
} else {
143+
return fun.apply(this, args);
144+
}
145+
};
146+
}
147+
203148
export {
204149
arrayEquals,
205150
arrayToObject,
206-
callbackify,
207151
flatten,
208152
max,
209153
mergeObjects,
210-
once,
211154
oneArrayIsStrictSubArrayOfOther,
212155
oneArrayIsSubArrayOfOther,
213156
oneSetIsSubArrayOfOther,
214157
pick,
215-
promisedCallback,
216-
toPromise,
158+
resolveToCallback,
217159
uniq
218160
};

0 commit comments

Comments
 (0)