Path: blob/trunk/third_party/closure/goog/labs/promise/promise.js
2868 views
// Copyright 2015 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Utilities for working with promises.16* Note that this file is written ES5-only.17*/1819goog.module('goog.labs.promise');2021var Promise = goog.require('goog.Promise');222324/**25* Executes an ES6 generator function that may yield Promises, blocking after26* each Promise until it settles. Within the generator, the value of each27* 'yield' expression becomes the resolved value of the yielded promise.28*29* If the generator function throws an exception or yields a rejected promise,30* execution stops, and the promise returned by this function is rejected.31*32* A typical call uses generator function syntax:33*34* goog.labs.promise.run(function*() {35* console.log('about to start waiting');36* while (needsToWait()) {37* // Wait 10 seconds.38* yield goog.Timer.promise(10000);39* console.log('still waiting...');40* }41* }).then(() => {42* console.log('done waiting');43* });44*45* This function can also be used to simplify asynchronous code:46*47* goog.labs.promise.run(function*()) {48* var x = yield somethingThatReturnsAPromise();49* var y = yield somethingElseThatReturnsAPromise();50* return x + y;51* }).then(sum => {52* console.log('The sum is:', sum);53* });54*55* @param {function(this: CONTEXT):TYPE} generatorFunc A function which is56* called immediately and returns a generator.57* @param {CONTEXT=} opt_context The context in which generatorFunc should be58* called.59* @return {!goog.Promise<TYPE>} A promise that is resolved when the generator60* returned from generatorFunc is exhausted, or rejected if an error occurs.61* If the generator function returns, this promise resolves to the returned62* value.63* @template CONTEXT, TYPE64*/65exports.run = function(generatorFunc, opt_context) {66var generator = generatorFunc.call(opt_context);67/**68* @param {*} previousResolvedValue69* @param {boolean=} opt_isRejected70*/71function loop(previousResolvedValue, opt_isRejected) {72var gen = opt_isRejected ? generator['throw'](previousResolvedValue) :73generator.next(previousResolvedValue);74if (!gen.done) {75// Wrap gen.value in a promise in case it isn't a promise already.76return Promise.resolve(gen.value).then(77function(resolvedValue) { return loop(resolvedValue); },78function(rejectValue) { return loop(rejectValue, true); });79}80return gen.value;81}82// Call loop() from then() to ensure exceptions are captured.83return Promise.resolve().then(loop);84};858687