blend / promise-utils Goto Github PK
View Code? Open in Web Editor NEWLodash-like, dependency-free utilities for native ES6 promises.
License: MIT License
Lodash-like, dependency-free utilities for native ES6 promises.
License: MIT License
Hi. Nice library!
I've found a bug where when trying to compile with parcel, it throws warnings: like:
⚠️ Could not load source file "../../src/index.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/index.js".
⚠️ Could not load source file "../../src/delay.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/delay.js".
⚠️ Could not load source file "../../src/invert.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/invert.js".
⚠️ Could not load source file "../../src/retry.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/retry.js".
⚠️ Could not load source file "../../src/settleAll.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/settleAll.js".
⚠️ Could not load source file "../../src/timeout.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/timeout.js".
⚠️ Could not load source file "../../src/memoize.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/memoize.js".
⚠️ Could not load source file "../../src/filter.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/filter.js".
⚠️ Could not load source file "../../src/map.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/map.js".
⚠️ Could not load source file "../../src/errors.ts" in source map of "../../node_modules/blend-promise-utils/dist/src/errors.js".
When looking in the dist folder, the *.js.map files shows the entrypoint to a file that does not exist in the build.
sources":["../../src/delay.ts"]
Solution1: Include the source in the npm package.
Solution2: Remove the sourcemaps?
This is a feature request for a defer
function that returns a value of the last invocation of a function. It's similar to caching/throttling/debouncing but I couldn't find any equivalent in this library or in Lodash. So I'm proposing this to see if any other people have similar use cases.
export const defer = <T, F extends (...args: never[]) => Promise<T>>(
callback: F
): ((...args: Parameters<F>) => Promise<T>) => {
let cache: Promise<T> | undefined = undefined;
return async (...args: Parameters<F>): Promise<T> => {
const lastCache = cache;
cache = callback(args);
return lastCache ?? cache;
};
};
it("defers a value", async () => {
const callback = defer(async (x: number) => x);
expect(await callback(1)).toBe(1);
expect(await callback(2)).toBe(1);
expect(await callback(3)).toBe(2);
expect(await callback(4)).toBe(3);
});
const fileContents = await promiseUtils.filter(
['file1', 'file2', 'file3'],
async fileName => {
const rawData = await fs.read(fileName);
return JSON.parse(rawData);
},
);
This snippet from the readme looks like it should be using promiseUtils.map, as there is no predicate/filtering, unless the filtering is "only keep the files that the raw data parses into something." If the latter is the case, for documentation I'd recommend refactoring this to something that clearly returns a boolean
The page says this is a javascript / typescript library but it isn't. It's pure javascript. There is zero type information when I install this into my project.
This is surprising since I see it is written with Typescript.
The settleAll
utility function should accept an array of async functions (or functions that returns promises), not an array of promises because it would cause triggering the needed functions before the right time and that is problematic...
Current implementation (based on docs):
const { results, errors } = await promiseUtils.settleAll([
asyncFunction1(),
asyncFunction2(),
asyncFunction3(),
]);
The right way for things to work:
const { results, errors } = await promiseUtils.settleAll([
asyncFunction1,
asyncFunction2,
asyncFunction3,
]);
flatMap should not map an empty array into the result, empty arrays should be ignored as per ECMA implementation of Array.prototype.flatMap
const { flatMap } = require("blend-promise-utils")
let input = [{
data: []
}, {
data: [1,2,3]
}]
const itaratee = input => input.data
const expected = input.flatMap(itaratee)
const actual = await flatMap(input, itaratee)
console.log('Expected: ' + JSON.stringify(expected))
console.log('Actual: ' + JSON.stringify(actual))
"Expected: [1,2,3]"
"Actual: [[],1,2,3]"
Hi,
Current behavior of settleAll
function is that if some promise throws an error, it is removed from the results
array and added to errors
array. This way the order of promises is broken and additionally, it's hard to guess, from which promise the errors comes. E.g.
/* As an example, secondPromise() throws an error */
const {
results: [
firstPromiseResult,
secondPromiseResult, // it contains thirdPromiseResult
thirdPromiseResult, // it is undefined
],
errors, // it contains array of single error of the second promise
} = await settleAll([
firstPromise(),
secondPromise(),
thirdPromise(),
]);
To my mind, it would be much more intuitive if the order of resolved promises and errors preserved:
/* As an example, secondPromise() throws an error */
const {
results: [
firstPromiseResult,
secondPromiseResult, // it contains null/undefined
thirdPromiseResult, // it contains thirdPromiseResult
],
errors, // it contains [null, secondPromiseError, null]
} = await settleAll([
firstPromise(),
secondPromise(),
thirdPromise(),
]);
I seem to have this need every so often and keep finding myself redefining the same function over and over again in multiple projects. The point of the function is to take an array of functions that produce a promise but will only start 10 (configurable) promises at a time.
A real-world example I've had recently was to download all the URLs listed in a file, with no more than 10 requests at a time:
const fileData = await fs.promises.readFile('urls.txt', 'utf-8') as string;
const fileLines = fileData.split('\n');
const promiseFuncs = fileLines.map((l) => () => downloadUrl(l));
await promiseThrottle(promiseFuncs, 10);
The code for promiseThrottle
looks like this:
export async function promiseThrottle(promiseFuncs: any[], max = 10) {
const executingPromises = [];
const results = [];
while (executingPromises.length !== 0 || promiseFuncs.length !== 0) {
while (executingPromises.length < max && promiseFuncs.length !== 0) {
const promise = promiseFuncs.shift()().then((result: any) => {
promise.done = true;
return result;
});
executingPromises.push(promise);
}
results.push(await Promise.race(executingPromises));
executingPromises.splice(executingPromises.findIndex((p) => p.done), 1);
}
return results;
}
In the above example, downloadUrl
saves to disk as a side-effect (because there were 1000s of web pages) but it could also return its results when all promises have been run.
Do you think there's a place for something like this functionality in promiseUtils
?
The JSDoc on map
indicates that input
can be an iterable, however it doesn't seem to work with other objects that implement the iterable protocol including built-in ones like Set
.
const P = require('blend-promise-utils');
const main = async function () {
const numbers = new Set([1, 2, 3]);
await P.map(numbers, function (number) {
console.log(number);
});
};
main();
1
2
3
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.