Hows about a module?
10 likes and I'll publish it
wait-in-line
Example usage
const Line = require('wait-in-line')
const waitInLine = Line()
// a continuable with no side efect
waitInLine(done => setTimeout(done, 500))
waitInLine(done => {
process.stdout.write('IS ANYBODY OUT THERE?!')
done()
})
// async
waitInLine(done => {
fs.writeFile('/tmp/hello.txt', 'HELLLO?!!', (err, data) => {
if (err) alert('failed to save')
else alert('saved!')
done()
})
}
Src
const pull = require('pull-stream')
const Pushable = require('pull-pushable')
const pullParaMap = require('pull-paramap')
module.exports = function Line (width = 10) {
const queue = Pushable()
pull(
queue,
pullParaMap((continuable, done) => continuable(done), width),
pull.drain()
)
return (continuable) => queue.push(continuable)
}
or without await, perhaps even nicer:
async function getPersonMinimal (_, profileId) {
// make a Promise (so we can return some thing)
return new Promise((resolve, reject) => {
// set a our query *ready* to be run
const runQuery = (done) => {
apollo.query(getPersonMinimal(profileId))
.then(res => {
if (res.errors) reject(res.errors) // graphql errors
else resolve(res.data.person)
})
.catch(err => reject(err)) // network errors
.finally(done)
}
queue.push(runQuery)
})
}
pull(
queue,
pullParaMap((continuable, done) => continuable(done), 10),
pull.drain()
)
// My vuex action that was getting hammered
// actions here play well with Promises
async function getPersonMinimal (_, profileId) {
// make a Promise (so we can return some thing)
return new Promise((resolve, reject) => {
// set a our query *ready* to be run
const runQuery = async (done) => {
try {
const res = await apollo.query(getPersonMinimal(profileId))
if (res.errors) throw res.errors
resolve(res.data.person)
} catch (err) {
reject(err)
}
done()
}
// stick this in the queue of things to run,
// along with the resolve / reject for handling the results
queue.push(runQuery)
})
}
oh it's exquisite now @Nico [ Perihelion ]
I knew this pattern felt familiar : https://github.com/Raynos/continuable . This is a trippy data flow to get your head around aye.
oh yeah duh, that's so obvious now you point it out.
SO MUCH CLEANER
@staltz this works... but is it gross?
I don't know enough about async iterables to make one which you can push things into like this... pull-pushable
just works...
Had a tricky situation where my UI was trying to load profile info for 5000 profiles (for #ahau)... and apollo apparently just shits itself if you make that many concurrent requests.
So I made a janky queue with pull-streams:
const pull = require('pull-stream')
const Pushable = require('pull-pushable')
const pullParaMap = require('pull-paramap')
const queue = Pushable()
pull(
queue,
pullParaMap(
([runPromise, resolve, reject], cb) => {
runPromise()
.then(resolve)
.catch(reject)
.finally(() => cb(null))
},
10 // how many runPromise you can run concurrently
),
pull.drain()
)
// My vuex action that was getting hammered
// actions here play well with Promises
async function getPersonMinimal (_, profileId) {
// make a Promise (so we can return some thing)
return new Promise((resolve, reject) => {
// set a our query *ready* to be run
const runQuery = async () => {
try {
const res = await apollo.query(getPersonMinimal(profileId))
if (res.errors) throw res.errors
return res.data.person
} catch (err) {
// oh no!
}
}
// stick this in the queue of things to run,
// along with the resolve / reject for handling the results
queue.push([runQuery, resolve, reject])
})
}
Show whole feed