Skip to content

Instantly share code, notes, and snippets.

@davestewart
Last active October 20, 2020 15:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davestewart/053e0c1bc859ffcd275df8ae88531aa4 to your computer and use it in GitHub Desktop.
Save davestewart/053e0c1bc859ffcd275df8ae88531aa4 to your computer and use it in GitHub Desktop.
Modify a function so it only resolves the last call
// decorated search function
const search = last(function (query) {
return new Promise(function (resolve, reject) {
setTimeout(() => {
// randomly fail
Math.random() < .25
? reject(new Error('failed for query ' + query))
: resolve(String(query).toUpperCase())
}, Math.random() * 2000)
})
})
// demo api
const api = {
loading: false,
async search (query) {
this.loading = true
const results = await search(query) // only the final call will resolve
this.loading = false
return results
}
}
// user types query, a..b..c... in real world, you would debounce this too
let query = ''
for (let i = 0; i < 10; i++) {
query += String.fromCharCode(97 + i)
api.search(query)
.then(result => {
console.log('result:', result) // result: ABCDEFGHIJ
})
.catch(err => {
console.log('error:', err.message) // error: failed for query abcdefghij
})
}
/**
* Decorate a function to resolve only the last call
*
* @param {Function} callback an asynchronous function
* @returns a decorated asynchronous function that resolves only the last call
*/
function last (callback) {
let lastId = 0
async function call (...args) {
const id = ++lastId
return Promise
.resolve(callback(...args))
.then(result => {
return { id, result }
})
.catch(error => {
return { id, error }
})
}
return function (...args) {
return new Promise(async function (resolve, reject) {
return call(...args)
.then(function ({ id, result, error }) {
if (id === lastId) {
result
? resolve(result)
: reject(error)
}
})
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment