# All files / dist async-cache.js

13.79% Statements 4/29
23.08% Branches 3/13
0% Functions 0/11
17.39% Lines 4/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    3x

    3x
    3x

    3x
     "use strict";
    var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
            function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    };
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.AsyncCache = void 0;
    // Cache which avoids concurrently getting the same thing more than once.
    class AsyncCache {
        constructor(fn) {
            this._attempts = new Map();
            this._fn = fn;
        }
        get(k) {
            const cached = this._attempts.get(k);
            if (cached) {
                return cached;
            }
            // This can throw, even though we do not
            // await the promise. Because of this,
            // we need to construct p outside of
            // attempt. If p was constructed in the attempt
            // there is a subtle timing bug.
            // 1. The 'attempt' promise starts to be constructed.
            // 2. Within the attempt promise, calling this._fn(k) fails
            //    before the await. This means that the catch is called
            //    synchronously.
            // 3. Within the catch, we delete this._attempts[k].
            // 4. 'attempt' is constructed successfully as a failed promise.
            // 5. Finally, this._attempts is set - but in a perpetually
            //    failed state.
            // By constructing the promise here, if the construction
            // fails then it never ends up in _attempts and this throws
            // right away.
            const p = this._fn(k);
            // This shares concurrent attempts, but still retries on failure.
            const attempt = (() => __awaiter(this, void 0, void 0, function* () {
                try {
                    return yield p;
                }
                catch (e) {
                    // By removing the cached attempt we ensure this is retried
                    this._attempts.delete(k);
                    throw e;
                }
            }))();
            this._attempts.set(k, attempt);
            return attempt;
        }
    }
    exports.AsyncCache = AsyncCache;
    //# sourceMappingURL=async-cache.js.map