0

I'm trying to use the result of a promise function in a non-asynchronous manner. It doesn't matter how long the calculation of the digest will take - I just want the execution of the code to wait (block, hibernate, stop, ...) until there is a result for the promise:

async function sha1(str) {
    const r = await crypto.subtle.digest(`SHA-1`, new TextEncoder().encode(str));
    return Array.prototype.map.call(new Uint8Array(r), x => x.toString(16).padStart(2, 0)).join(``);
}

function test(str) {
    return sha1(str);
}

console.log(1);
console.log(test("abc"));
console.log(3);
console.log(test("def"));

As long as I don't go into details in the debugger, the resulting console-log is always in a "pending" state.

[Log] 1 
[Log] Promise {status: "pending"}
[Log] 3 
[Log] Promise {status: "pending"}

After opening the detail there is the correct result for each function call:

[Log] Promise
result: "a9993e364706816aba3e25717850c26c9cd0d89d"
status: "resolved"
...

I'm pretty sure I will get a "duplicate question" tag - but I couldn't find a satisfying answer. Sorry about that. Most of the examples just use an output function for demonstration purposes, but I need to return a value from the second function...

Denis Giffeler
  • 1,499
  • 12
  • 21
  • 1
    `sha1` returns an unresolved promise. It resolves sometime after your `console.log` call (which is how you can inspect it in the console). There is no way to block until the promise resolves, but you can `await` it (from inside an `async` function). – Alexander O'Mara Jan 17 '18 at 22:35
  • `sha1` returns a pending promise, synchronously, so, yes, there is a pending promise – Jaromanda X Jan 17 '18 at 22:36
  • If your logs are at the root level, there is no way to halt until the promise is resolved. If you put them in an async function, you can `console.log(await test("abc"))`, and it will wait for each result before the logging continues. – CRice Jan 17 '18 at 22:36
  • 1
    ALL async functions return a promise (this is a common misunderstanding). You have to use `.then()` or `await` on that promise to get the value. That's how it works. While programming with `await` appears to make it look like synchronous code, it's still async. – jfriend00 Jan 17 '18 at 22:36
  • 1
    note, calling `test('abc')` is no different than calling `sha1('abc')` - adding a level of "indirection" doesn't make asynchronous code synchronous – Jaromanda X Jan 17 '18 at 22:37
  • @AlexanderO'Mara: Thank you - if I use nested calls I have to mark every function (even eventhandlers) as async. Using await in the test function doesn't change the behaviour of the script. – Denis Giffeler Jan 17 '18 at 22:50
  • @jfriend00: I tried to change the "test" function (a lot!) but couldn't figure out how to get the work done. sha1(str).then(result => {return result;}) is not going to do the trick... – Denis Giffeler Jan 17 '18 at 22:53
  • 2
    If you're trying to get a synchronous result out of an asynchronous operation, you can just give up now. Javascript does not have that capability. You're going to be using a promise-based async result inside of a `.then()` handler or with an `await` no matter what. Async is considered infectious. Once a result is async, anything that uses it has to be async. So your `test()` function needs to have an asynchronous interface, not a synchronous one. – jfriend00 Jan 17 '18 at 22:55
  • @jfriend00: »It's turtles all the way down (or up)«...I was missing this simple advice of yours in all the blogs I read. Even if this question is marked as duplicate (as foreseen) - it should be made more clearly in the manuals about promises and async/await. Thank you. – Denis Giffeler Jan 18 '18 at 07:57
  • The first line of the [Description section for an Async Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#Description) on MDN is this: ***"When an async function is called, it returns a Promise. When the async function returns a value, the Promise will be resolved with the returned value. When the async function throws an exception or some value, the Promise will be rejected with the thrown value."*** – jfriend00 Jan 18 '18 at 08:01
  • 1
    The descriptions of `await` do appear to be lacking as they don't help people understand that the host function still returns the promise immediately even though the function body is itself paused for an `await`. An implementation of `await` can be thought of to be a compiler created `.then()` handler that automatically contains all code that follows the `await`. And, just like when not using `await`, the host function still returns its promise even though the promise you are awaiting has not yet resolved/rejected. `await` really only affects things inside the function body it's in. – jfriend00 Jan 18 '18 at 08:04

0 Answers0