Suppose we are using the `fetchWeekDay` function from the introduction to fetch the current weekday in multiple timezones:

``` javascript
import { main } from 'effection';
import { fetchWeekDay } from './fetch-week-day';

main(function*() {
  let dayUS = yield* fetchWeekDay('est');
  let daySweden = yield* fetchWeekDay('cet');
  console.log(`It is ${dayUS}, in the US and ${daySweden} in Sweden!`);
});
```

This works, but it slightly inefficient because we are running the fetches one
after the other. How can we run both `fetch` operations at the same time?

## Using `async/await`

If we were just using `async/await` and not using Effection, we might do
something like this to fetch the dates at the same time:

``` javascript
async function() {
  let dayUS = fetchWeekDay('est');
  let daySweden = fetchWeekDay('cet');
  console.log(`It is ${await dayUS}, in the US and ${await daySweden} in Sweden!`);
}
```

Or we could use a combinator such as `Promise.all`:

``` javascript
async function() {
  let [dayUS, daySweden] = await Promise.all([fetchWeekDay('est'), fetchWeekDay('cet')]);
  console.log(`It is ${dayUS}, in the US and ${daySweden} in Sweden!`);
}
```

## Dangling Promises

This works fine as long as both fetches complete successfully, but what happens
when one of them fails? Since there is no connection between the two tasks, a
failure in one of them has no effect on the other. We will happily keep trying
to fetch the US date, even when fetching the Swedish date has already failed!

For `fetch`, the consequences of this are not so severe, the worst that happens is
that we have a request which is running longer than necessary, but you can imagine
that the more complex the operations we're trying to combine, the more opportunity
for problems there are.

We call these situations "dangling promises", and most significantly complex
JavaScript applications suffer from this problem. `async/await` fundamentally does
not handle cancellation very well when running multiple operations concurrently.

## With Effection

How does Effection deal with this situation? If we wrote the example using
Effection in the exact same way as the `async/await` example, then we will find
that it doesn't behave the same:

``` javascript
import { main } from 'effection';
import { fetchWeekDay } from './fetch-week-day';

main(function*() {
  let dayUS = fetchWeekDay('est');
  let daySweden = fetchWeekDay('cet');
  console.log(`It is ${yield* dayUS}, in the US and ${yield* daySweden} in Sweden!`);
});
```

This is still running one fetch after the other, and is not fetching both at
the same time!

To understand why, remember that unlike calling an async function to
create a `Promise`, calling a generator function to create an
[`Operation`][Operation] does not do anything by itself. An `Operation` is
is only evaluated when passed to `yield*` or to `run()`. Therefore it isn't
until we `yield*` do we actually start to fetch the dates.

We could use `run` here to run our operations, and then wait for them, but this
is not the correct way:

``` javascript
// THIS IS NOT THE CORRECT WAY!
import { main, run } from 'effection';
import { fetchWeekDay } from './fetch-week-day';

main(function*() {
  let dayUS = run(fetchWeekDay('est'));
  let daySweden = run(fetchWeekDay('cet'));
  console.log(`It is ${yield* dayUS}, in the US and ${yield* daySweden} in Sweden!`);
});
```

This has the same problem as our `async/await` example: a failure in one fetch
has no effect on the other!

## Introducing `spawn`

The `spawn` operation is Effection's solution to this problem!

``` javascript
import { main, spawn } from 'effection';
import { fetchWeekDay } from './fetch-week-day';

main(function*() {
  let dayUS = yield* spawn(() => fetchWeekDay('est'));
  let daySweden = yield* spawn(() => fetchWeekDay('cet'));
  console.log(`It is ${yield* dayUS}, in the US and ${yield* daySweden} in Sweden!`);
});
```

Like `run` and `main`, `spawn` takes an `Operation` and returns a `Task`. The
difference is that this `Task` becomes a child of the current `Task`. This
means it is impossible for this task to outlive its parent. And it also means
that an error in the task will cause the parent to fail.

You can think of this as creating a hierarchy like this:

```
+-- main
  |
  +-- fetchWeekDay('est')
  |
  +-- fetchWeekDay('cet')
```

When `fetchWeekDay('cet')` fails, since it was spawned by `main`, it will also
cause `main` to fail. When `main` fails it will make sure that none of its
children outlive it, and it will `halt` all of its remaining children. We end
up with a situation like this:

```
+-- main [FAILED]
  |
  +-- fetchWeekDay('est') [HALTED]
  |
  +-- fetchWeekDay('cet') [FAILED]
```

Effection tasks are tied to the lifetime of their parent, and it becomes
impossible to create a task whose lifetime is undefined. Because of this, the
behaviour of errors is very clearly defined. An error in a child will also
cause the parent to error, which in turn halts any siblings.

This idea is called [structured concurrency], and it has profound effects on
the composability of concurrent code.

## Using combinators

We previously showed how we can use the `Promise.all` combinator to implement
the concurrent fetch. Effection also ships with some combinators, for example
we can use the `all` combinator:

``` javascript
import { all, main } from 'effection';

main(function *() {
  let [dayUS, daySweden] = yield* all([fetchWeekDay('est'), fetchWeekDay('cet')]);
  console.log(`It is ${dayUS}, in the US and ${daySweden} in Sweden!`);
});
```

## Spawning in a Scope

The `spawn()` operation always runs its operation as a child of the current
operation. Sometimes however, you might want to run an operation as a child of a
_different_ operation. To do this we can use the [`Scope#run()`][scope.run]
method.

This is often useful when integrating Effection into existing promise or
callback based frameworks. The following example creates a trivial
[`express`][express] server that runs each request as an operation that is
a child of the main operation.


```javascript {5,8}
import express from 'express';
import { main, suspend, useScope } from "effection";

await main(function*() {
  let scope = yield* useScope();
  let app = express();
  app.get("/", async (_, res) => {
    await scope.run(function*() {
      res.send("Hello World!");
    })
  });
  let server = app.listen();
  try {
    yield* suspend()
  } finally {
    server.close();
  }
});
```

We capture a reference to the main operation's scope in line **(5)**
and then use that scope to run the request as an async function on
line **(8)**.

You can learn more about this in the [scope guide](./scope).

[structured concurrency]: https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/
[express]: https://expressjs.org
[scope.run]: /api/v3/Scope#method_run_0
[Operation]: /api/v3/Operation
