February 14, 2019
TestsSource
- for-of with async+await
- having `await` inside `forEach`
- iterate over list of promises
Source Code
The source code we wrote during the event.
async-iterators.spec.js
import assert from 'assert';
describe('for-of with async+await', () => {
it('iterate over array of async, using for-of, each values resolves', async () => {
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
for (const x of ps) {
results.push(await x);
}
assert.deepEqual([1, 2], results);
});
it('order will remain, no matter the timing', async () => {
const p1 = new Promise((resolve) => { setTimeout(() => resolve(1), 100) });
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
for (const x of ps) {
results.push(await x);
}
assert.deepEqual([1, 2], results);
});
it('rejecting a promise, will break the execution of `for` loop', async () => {
const p1 = Promise.reject(1);
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
try {
for (const x of ps) {
results.push(await x);
}
assert(false, 'The code should never get here, because the for loop should throw');
} catch (e) {
assert.deepEqual([], results);
}
});
it('fill an array until a rejected promise', async () => {
const p1 = Promise.resolve(1);
const p2 = Promise.reject(2);
const ps = [p1, p2];
const results = [];
try {
for (const x of ps) {
results.push(await x);
}
assert(false, 'The code should never get here, because the for loop should throw');
} catch (e) {
assert.deepEqual([1], results);
}
});
it('fill an array until a rejected promise (and not beyond)', async () => {
const p1 = Promise.resolve(1);
const p2 = Promise.reject(2);
const p3 = Promise.resolve(1);
const ps = [p1, p2, p3];
const results = [];
try {
for (const x of ps) {
results.push(await x);
}
assert(false, 'The code should never get here, because the for loop should throw');
} catch (e) {
assert.deepEqual([1], results);
}
});
});
describe('having `await` inside `forEach`', () => {
it('`forEach` over array of promise, expect NO elements to return', async () => {
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
ps.forEach(async (p) => { results.push(await p) });
assert.deepEqual([], results);
});
it('`forEach` over array of promise, expect all elements to return, WHEN we delay the assert', async () => {
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
ps.forEach(async (p) => { results.push(await p) });
await new Promise(resolve => setTimeout(resolve, 0));
assert.deepEqual([1,2], results);
});
it('`forEach` over array of promise, expect all elements to return, WHEN we delay the assert, even 1000 times', async () => {
let x = 0;
while (x++ < 100) {
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
ps.forEach(async (p) => { results.push(await p) });
await new Promise(resolve => setTimeout(resolve, 0));
assert.deepEqual([1, 2], results);
}
});
it('two delayed promises (with the same delay) the order stays (also many times)', async () => {
let x = 0;
while (x++ < 200) {
const p1 = new Promise(resolve => setTimeout(() => resolve(1), 2));
const p2 = new Promise(resolve => setTimeout(() => resolve(2), 2));
const ps = [p1, p2];
const results = [];
ps.forEach(async (p) => { results.push(await p) });
await new Promise(resolve => setTimeout(resolve, 2));
assert.deepEqual([1, 2], results);
}
}).timeout(10000);
it('dont wait long enough after the `forEach` for the asyncs to finish', async () => {
const p1 = new Promise(resolve => setTimeout(() => resolve(1), 4));
const p2 = new Promise(resolve => setTimeout(() => resolve(2), 4));
const ps = [p1, p2];
const results = [];
ps.forEach(async (p) => { results.push(await p) });
await new Promise(resolve => setTimeout(resolve, 2));
assert.deepEqual([], results);
});
// it will endlessly block
// it('setTimeout is not called when we dont exit the current callstack', async () => {
// const p1 = new Promise(resolve => setTimeout(() => resolve(1), 2));
// const p2 = new Promise(resolve => setTimeout(() => resolve(2), 2));
// const ps = [p1, p2];
// const results = [];
// ps.forEach(async (p) => { results.push(await p) });
// while (results.length < ps.length) {}
// assert.deepEqual([1,2], results);
// });
});
describe('iterate over list of promises', () => {
it('collect the results 2 resolving promises, works', async () => {
const promises = [Promise.resolve(1), Promise.resolve(2)];
let results = [];
for await (const p of promises) {
results.push(p);
}
assert.deepEqual([1,2], results);
});
it('reject one promise (of the array), throws', async () => {
const p1 = Promise.reject(1);
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
try {
for await (const x of ps) {
results.push(x);
}
assert(false, 'The code should never get here, because the for loop should throw');
} catch (e) {
assert.deepEqual([], results);
}
});
it('collect results we await for ... dont do it :)', async () => {
let p1 = Promise.resolve(1);
let p2 = Promise.resolve(2);
const ps = [p1, p2];
for await (const x of ps) {
if (ps.length < 10) {
ps.push(x);
}
}
assert.deepEqual([p1,p2,1,2,1,2,1,2,1,2], ps);
});
it('promise order depends on timing', async () => {
const p1 = new Promise((resolve) => { setTimeout(() => resolve(1), 100) });
const p2 = Promise.resolve(2);
const ps = [p1, p2];
const results = [];
for await (const x of ps) {
results.push(x);
}
assert.deepEqual([1, 2], results);
});
it('We dont expect to get into the for-loop, iterating over empty array', async () => {
for await (const x of []) {
assert(false, 'We dont expect to get into the for-loop')
}
});
it('will for-await loop wait for all promises inside of it', async () => {
try {
for await (const x of [1]) {
const f = async () => { throw Error('failsss'); };
await f();
}
} catch (e) {
assert(true);
}
});
xit('will for-await loop wait for all promises inside of it', async () => {
try {
for await (const x of [1]) {
const f = async () => { throw Error('failsss'); };
f();
assert(true);
}
} catch (e) {
assert(false, 'should not get here');
}
});
});