-
-
Save jonurry/29fc4bf7b85d103b7842090deba86fd3 to your computer and use it in GitHub Desktop.
// my solution | |
async function locateScalpel(nest) { | |
let results = network(nest).map(async name => { | |
// if the name of the nest that was last known to hold the scalpel | |
// is the current nest then we have found the scalpel | |
// else, return null | |
if (name === await anyStorage(nest, name, 'scalpel')) { | |
return name; | |
} else { | |
return null; | |
} | |
}); | |
// get the name of the nest that is not null | |
return (await Promise.all(results)).filter(nest => nest !== null)[0]; | |
} | |
// official answer | |
async function locateScalpel(nest) { | |
let current = nest.name; | |
for (;;) { | |
let next = await anyStorage(nest, current, "scalpel"); | |
if (next == current) return current; | |
current = next; | |
} | |
} | |
// my solution without async/await, just a promise | |
function locateScalpel2(nest) { | |
// recursively search nests until scalpel is found | |
function findScalpel(nextNest) { | |
// check nextNest for scalpel | |
return anyStorage(nest, nextNest, 'scalpel') | |
.then(value => { | |
if (value == nextNest) { | |
// found scalpel | |
return value; | |
} else { | |
// continue search from last nest known to contain scalpel | |
return findScalpel(value); | |
} | |
}); | |
} | |
// start search at current nest | |
return findScalpel(nest.name); | |
} | |
// oficial answer | |
function locateScalpel2(nest) { | |
function loop(current) { | |
return anyStorage(nest, current, "scalpel").then(next => { | |
if (next == current) return current; | |
else return loop(next); | |
}); | |
} | |
return loop(nest.name); | |
} | |
locateScalpel(bigOak).then(value => console.log('1st:', value)); | |
// → Butcher Shop | |
locateScalpel2(bigOak).then(value => console.log('2nd:', value)); | |
// → Butcher Shop |
Hints
This can be done with a single loop that searches through the nests, moving forward to the next when it finds a value that doesn’t match the current nest’s name and returning the name when it finds a matching value. In the async
function, a regular for
or while
loop can be used.
To do the same in a plain function, you will have to build your loop using a recursive function. The easiest way to do this is to have that function return a promise by calling then
on the promise that retrieves the storage value. Depending on whether that value matches the name of the current nest, the handler returns that value or a further promise created by calling the loop function again.
Don’t forget to start the loop by calling the recursive function once from the main function.
In the async
function, rejected promises are converted to exceptions by await
. When an async
function throws an exception, its promise is rejected. So that works.
If you implemented the non-async
function as outlined above, the way then
works also automatically causes a failure to end up in the returned promise. If a request fails, the handler passed to then
isn’t called, and the promise it returns is rejected with the same reason.
Asynchronous Programming
11.1 Tracking The Scalpel
The village crows own an old scalpel that they occasionally use on special missions—say, to cut through screen doors or packaging. To be able to quickly track it down, every time the scalpel is moved to another nest, an entry is added to the storage of both the nest that had it and the nest that took it, under the name
"scalpel"
, with its new location as value.This means that finding the scalpel is a matter of following the breadcrumb trail of storage entries until you find a nest where that points at the nest itself.
Write an
async
functionlocateScalpel
that does this, starting at the nest on which it runs. You can use theanyStorage
function defined earlier to access storage in arbitrary nests. The scalpel has been going around long enough that you may assume that every nest has a"scalpel"
entry in its data storage.Next, write the same function again without using
async
andawait
.Do request failures properly show up as rejections of the returned promise in both versions? How?