Merge pull request #2328 from overleaf/em-project-imports

Move ProjectEntityMongoUpdateHandler to async/await

GitOrigin-RevId: e5c0d4a7ece34c3ded89b6eae3673135061f375a
This commit is contained in:
Timothée Alby
2019-11-12 09:15:18 +00:00
committed by sharelatex
parent e3c8de035a
commit 3bd15b1a47
8 changed files with 3444 additions and 4 deletions
+82 -2
View File
@@ -3,6 +3,8 @@ const pLimit = require('p-limit')
module.exports = {
promisifyAll,
promisifyMultiResult,
callbackifyMultiResult,
expressify,
promiseMapWithLimit
}
@@ -19,22 +21,100 @@ module.exports = {
*
* This will not magically fix all modules. Special cases should be promisified
* manually.
*
* The second argument is a bag of options:
*
* - without: an array of function names that shouldn't be promisified
*
* - multiResult: an object whose keys are function names and values are lists
* of parameter names. This is meant for functions that invoke their callbacks
* with more than one result in separate parameters. The promisifed function
* will return these results as a single object, with each result keyed under
* the corresponding parameter name.
*/
function promisifyAll(module, opts = {}) {
const { without = [] } = opts
const { without = [], multiResult = {} } = opts
const promises = {}
for (const propName of Object.getOwnPropertyNames(module)) {
if (without.includes(propName)) {
continue
}
const propValue = module[propName]
if (typeof propValue === 'function') {
if (typeof propValue !== 'function') {
continue
}
if (multiResult[propName] != null) {
promises[propName] = promisifyMultiResult(
propValue,
multiResult[propName]
).bind(module)
} else {
promises[propName] = promisify(propValue).bind(module)
}
}
return promises
}
/**
* Promisify a function that returns multiple results via additional callback
* parameters.
*
* The promisified function returns the results in a single object whose keys
* are the names given in the array `resultNames`.
*
* Example:
*
* function f(callback) {
* return callback(null, 1, 2, 3)
* }
*
* const g = promisifyMultiResult(f, ['a', 'b', 'c'])
*
* const result = await g() // returns {a: 1, b: 2, c: 3}
*/
function promisifyMultiResult(fn, resultNames) {
function promisified(...args) {
return new Promise((resolve, reject) => {
try {
fn(...args, (err, ...results) => {
if (err != null) {
return reject(err)
}
const promiseResult = {}
for (let i = 0; i < resultNames.length; i++) {
promiseResult[resultNames[i]] = results[i]
}
resolve(promiseResult)
})
} catch (err) {
reject(err)
}
})
}
return promisified
}
/**
* Reverse the effect of `promisifyMultiResult`.
*
* This is meant for providing a temporary backward compatible callback
* interface while we migrate to promises.
*/
function callbackifyMultiResult(fn, resultNames) {
function callbackified(...args) {
const [callback] = args.splice(-1)
fn(...args)
.then(result => {
const cbResults = resultNames.map(resultName => result[resultName])
callback(null, ...cbResults)
})
.catch(err => {
callback(err)
})
}
return callbackified
}
/**
* Transform an async function into an Express middleware
*