UNPKG

4.41 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
5 * This code may only be used under the BSD style license found at
6 * http://polymer.github.io/LICENSE.txt
7 * The complete set of authors may be found at
8 * http://polymer.github.io/AUTHORS.txt
9 * The complete set of contributors may be found at
10 * http://polymer.github.io/CONTRIBUTORS.txt
11 * Code distributed by Google as part of the polymer project is also
12 * subject to an additional IP rights grant found at
13 * http://polymer.github.io/PATENTS.txt
14 */
15var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
16 return new (P || (P = Promise))(function (resolve, reject) {
17 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
20 step((generator = generator.apply(thisArg, _arguments || [])).next());
21 });
22};
23Object.defineProperty(exports, "__esModule", { value: true });
24const cancel_token_1 = require("cancel-token");
25const cancel_token_2 = require("./cancel-token");
26/**
27 * A map from keys to promises of values. Used for caching asynchronous work.
28 */
29class AsyncWorkCache {
30 constructor(from) {
31 if (from) {
32 this._keyToResultMap = new Map(from._keyToResultMap);
33 }
34 else {
35 this._keyToResultMap = new Map();
36 }
37 }
38 /**
39 * If work has already begun to compute the given key, return a promise for
40 * the result of that work.
41 *
42 * If not, compute it with the given function.
43 *
44 * This method ensures that, in the absence of cancellations, we will only try
45 * to compute the value for `key` once, no matter how often or with what
46 * timing getOrCompute is called, even recursively.
47 *
48 * This API is safe for multiple, independently cancellable callers. So long
49 * as the given cancelToken is not cancelled, this function will not reject
50 * with a Cancel exception.
51 */
52 getOrCompute(key, compute, cancelToken = cancel_token_2.neverCancels) {
53 return __awaiter(this, void 0, void 0, function* () {
54 cancelToken.throwIfRequested();
55 while (true) {
56 try {
57 const result = yield this._getOrCompute(key, compute);
58 cancelToken.throwIfRequested();
59 return result;
60 }
61 catch (err) {
62 cancelToken.throwIfRequested();
63 if (cancel_token_1.isCancel(err)) {
64 // Ok, whoever was working on computing `key` was cancelled, but it
65 // wasn't us because we're not cancelled. Let's try again!.
66 continue;
67 }
68 throw err;
69 }
70 }
71 });
72 }
73 _getOrCompute(key, compute) {
74 return __awaiter(this, void 0, void 0, function* () {
75 const cachedResult = this._keyToResultMap.get(key);
76 if (cachedResult) {
77 return cachedResult;
78 }
79 const promise = (() => __awaiter(this, void 0, void 0, function* () {
80 // Make sure we wait and return a Promise before doing any work, so that
81 // the Promise is cached before control flow enters compute().
82 yield Promise.resolve();
83 return compute();
84 }))();
85 this._keyToResultMap.set(key, promise);
86 try {
87 yield promise;
88 }
89 catch (err) {
90 if (cancel_token_1.isCancel(err)) {
91 this._keyToResultMap.delete(key);
92 }
93 throw err;
94 }
95 return promise;
96 });
97 }
98 delete(key) {
99 this._keyToResultMap.delete(key);
100 }
101 clear() {
102 this._keyToResultMap.clear();
103 }
104 set(key, value) {
105 this._keyToResultMap.set(key, Promise.resolve(value));
106 }
107 has(key) {
108 return this._keyToResultMap.has(key);
109 }
110}
111exports.AsyncWorkCache = AsyncWorkCache;
112//# sourceMappingURL=async-work-cache.js.map
\No newline at end of file