←back to thread

517 points bkolobara | 3 comments | | HN request time: 1.167s | source
Show context
johnfn ◴[] No.45049034[source]
I think Rust is awesome and I agree with that part of the article.

What I disagree with is that it's the fault of Typescript that the href assignment bug is not caught. I don't think that has anything to do with Typescript. The bug is that it's counter-intuitive that setting href defers the location switch until later. You could imagine the same bug in Rust if Rust had a `set_href` function that also deferred the work:

    set_href('/foo');

    if (some_condition) {
        set_href('/bar');
    }
Of course, Rust would never do this, because this is poor library design: it doesn't make sense to take action in a setter, and it doesn't make sense that assigning to href doesn't immediately navigate you to the next page. Of course, Rust would never have such a dumb library design. Perhaps I'm splitting hairs, but that's not Rust vs TypeScript - it's Rust's standard library vs the Web Platform API. To which I would totally agree that Rust would never do something so silly.
replies(7): >>45049104 #>>45049184 #>>45049492 #>>45049625 #>>45049709 #>>45052032 #>>45052981 #
1. socalgal2 ◴[] No.45052981[source]
That is not a repo of the code in the article. The article's code is effectively

    set_href('/foo');

    let future = doSomethingElse()
    block_on(future)

    if (some_condition) {
        set_href('/bar');
    }
This code makes the bug clearer. doSomethingElse is effectively allowing the page to exit. this would be no different in many apps, even in rust.

The browser does not start a process when you set `window.location.href`. It starts a process after your code exits and lets the event loop run other tasks. The `await` in the example code is what allow other tasks to run, including the task to load a new page, (or quit an app, etc..) That task that was added when you set `window.location.href`

If that's not clear

    // task 1
    window.location.href = '/foo' // task2 (queues task2 to load the page)

    let content = await response.json(); // adds task3 to load json
                                         // which will add task4
                                         // to continue when finished

    // task4
    if (content.onboardingDone) {
        window.location.href = "/dashboard";
    } else {
        window.location.href = "/onboarding";
    }
task2 runs after task1. task1 exits at the `await`. task2, clears out all the tasks. task3 and task4 never run.
replies(1): >>45062159 #
2. depressedpanda ◴[] No.45062159[source]
No, I think you misunderstand how it works. The problem is that task 4, as you call it, runs after the navigation triggered by the redirect value.

The the author expects the side-effect -- navigation to a new page -- of the window.location.href setter to abort the code running below it. This obviously won't happen because there is no return in the first if-statement.

replies(1): >>45077304 #
3. socalgal2 ◴[] No.45077304[source]
There is a return, it's disguised as "await"

*simplified*, the symantics of "await" are just syntactic sugar

    const value = await someFunction()
    console.log(value);
is syntactic sugar for

    return someFunction().then(function(value) {
      // this gets executed after the return IF
      // something else didn't remove all events like
      // loading a new page
      console.log(value);
    });