Abdelrahman Awad
Software Engineer @Rasayel. Open-Source contributor.
In computer science, future, promise, delay, and deferred refer to constructs used for synchronizing program execution in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is not yet complete.
The term promise was proposed in 1976 by Daniel P. Friedman and David Wise,[1] and Peter Hibbard called it eventual
โThe Promise object is used for deferred and asynchronous computations. A Promise represents an operation that hasnโt completed yet, but is expected in the future.โ โ MDN Promise Reference
Pending
Fullfilled
Rejected
????????
What is the state of
const test = new Promise((resolve, reject) => {
resolve('Yay!');
});
What is the state of
const test = new Promise((resolve, reject) => {
reject('Nay!');
});
What is the state of
const test = new Promise((resolve, reject) => {
throw new Error('Yay?');
});
What is the state of
const test = new Promise((resolve, reject) => {
resolve('Yay!');
throw new Error('Huh?');
});
What is the state of
const test = new Promise((resolve, reject) => {
resolve('Yay!');
console.log('Did I get executed?');
});
What is the state of
const test = new Promise((resolve, reject) => {
resolve('Yay!');
console.log('Did I get executed?');
});
What is the state of
const test = new Promise((resolve, reject) => {
return;
resolve('Yay?');
console.log('Did I get executed?');
});
What is the state of
const test = new Promise((resolve, reject) => {
resolve('Yay!');
reject('Sorry ๐
I meant nay!');
});
What is the state of
const test = new Promise((resolve, reject) => {
resolve('Yay!');
}).then(value => {
throw new Error(value);
}).catch(err => {
console.log('error!');
});
How many times will it be logged
var p = new Promise((resolve, reject) => {
reject(Error('Can you fail twice?'))
})
p.catch(error => console.log(error.message))
p.catch(error => console.log(error.message))
code: serviceWorker.js
const generateQueryId = e.request
.clone()
.json()
.then(({ query, variables }) => {
// ....
});
const networkResponse = fromNetwork(e.request);
e.respondWith(
(async () => {
// ....
generateQueryId.then(queryId => {
// ... now I have the query id
})
// ... Returning the network response
return networkResponse.then(res => res.clone());
})()
);
e.waitUntil(
(async () => {
// ....
// re-using the network response
networkResponse.then(res => res.clone()).then(() => {
// ... do more stuff
});
generateQueryId.then(queryId => {
// ... now I have the query id again
})
// ....
})()
);
How many times will it be logged
const p = new Promise((resolve, reject) => {
return Promise.reject(Error('Can I fail twice!'))
})
p.catch(error => console.log(error.message))
p.catch(error => console.log(error.message))
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
fs.readdir(source).catch(err => {
console.log('Error finding files: ' + err)
}).then(files => {
files.forEach(function (filename, fileIndex) {
gm(source + filename).size().catch(err => {
console.log('Error identifying file size: ' + err)
}).then(values => {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename).catch(err => {
console.log('Error writing file: ' + err)
});
})
});
})
});
function getUserAddress () {
return new Promise(resolve => {
// MAKE API CALL...
});
}
function getUserEmail () {
return new Promise(resolve => {
// MAKE API CALL...
});
}
function makeOrder(email, address) {
return new Promise(resolve => {
// MAKE API CALL...
});
}
// before!
getUserEmail().then(email => {
getUserAddress().then(address => {
userData.address = address;
makeOrder(email, address).then(response => {
// ... more work
})
});
});
function getUserAddress () {
return new Promise(resolve => {
// MAKE API CALL...
});
}
function getUserEmail () {
return new Promise(resolve => {
// MAKE API CALL...
});
}
function makeOrder(email, address) {
return new Promise(resolve => {
// MAKE API CALL...
});
}
// before!
getUserEmail().then(email => {
return getUserAddress().then(address => ({ email, address }));
}).then(userData => {
return makeOrder(userData.email, userData.address);
}).then(response => {
// Single level of indentation!
});
fetch(uri, {
method: 'post',
body: JSON.stringify({
query: print(query),
variables
})
}).catch(err => {
throw new Error(err);
})
.then(res => res.json())
.then(data => {
})
Throttling promises one at a time
let queue = Promise.resolve();
function runInQueue(fn) {
queue = queue.then(() => fn());
}
runInQueue(() => Promise.resolve('Yay!'));
runInQueue(() => makeAPICall());
runInQueue(() => makeAPICall());
runInQueue(() => makeAPICall());
runInQueue(() => makeAPICall());
const queue = [];
function runInQueue(fn) {
queue.push(fn);
}
function startQueue() {
return queue.reduce((prev, curr) => {
return prev.then(() => curr());
}, Promise.resolve());
}
// Prepare Some Requests!
runInQueue(() => makeAPICall());
runInQueue(() => makeAPICall());
runInQueue(() => makeAPICall());
runInQueue(() => makeAPICall());
// Run them in sequeuence!
startQueue();
const queue = new PQueue({ concurrency: 1 });
function performSafeCartUpdate({ action, commit }) {
const handler = async ({ data, errors }) => {
if (errors) {
// eslint-disable-next-line no-console
console.error(errors[0].message);
}
const items = data.response.cart.items.map(mapCartItem);
// Sync the Cart back!
commit('SET_ITEMS', items);
commit('SET_SYNC_DATE', new Date());
await saveToIDB('cart', items);
};
queue.add(() =>
action().then(res => {
if (!queue.size) {
return handler(res);
}
})
);
}
code: store/cart.js
Promise.all([
makeAPICall(),
makeAPICall(),
makeAPICall(),
makeAPICall()
]).then(([res1, res2, res3, res4]) => {
// ...
});
async function getUserEmail() {
// ...
}
async function getUserAddress() {
// ...
}
const address = await getUserAddress();
const email = await getUserEmail();
Identify the 2 problems here ๐ค
async function getUserEmail() {
// ...
}
async function getUserAddress() {
// ...
}
(async () => {
const [email, address] = await Promise.all([
getUserEmail(),
getUserAddress()
]);
});
Fixed ๐ง
async function getUserEmail () {
// ...
}
function getUserEmail () {
return new Promise(resolve => {
// ...
// resolve(result)
});
}
const result = await someAsyncCode();
someAsyncCode().then(result => {
// Result!
});
function fn () {
return new Promise.resolve(10);
}
const result = await fn();
function fn () {
return 10;
}
// is this legal?
const result = await fn();
function sleep(wait) {
return new Promise(resolve => {
setTimeout(resolve, wait);
});
}
(async () => {
for (let i = 1; i <= 5; i++) {
await sleep(1000);
console.log('Slept for ' + 1000 * i);
}
})();
function sleep(wait) {
return new Promise(resolve => {
setTimeout(resolve, wait);
});
}
[1, 2, 3, 4, 5].forEach(async i => {
await sleep(1000);
console.log('Slept for ' + 1000 * i);
});
async logout({ commit, dispatch }) {
Cookies.remove('auth');
commit('SET_TOKEN', '');
commit('SET_USER', null);
await dispatch('cart/clear', undefined, { root: true });
// Don't wait for this, revoking token in background!
this.$api.mutate({
mutation: RevokeToken
});
}
const networkResponse = fromNetwork(e.request);
e.respondWith(
(async () => {
// get the request body.
const queryId = await generateQueryId;
const cachedResult = queryId && (await fromCache(queryId));
if (cachedResult) {
return cachedResult;
}
return networkResponse.then(res => res.clone());
})()
);
e.waitUntil(
(async () => {
try {
const res = await networkResponse.then(res => res.clone());
const queryId = await generateQueryId;
if (queryId) {
await saveToCache(queryId, res);
}
} catch (err) {
// eslint-disable-next-line no-console
console.log(err);
}
})()
);
By Abdelrahman Awad