{"id":15093038,"url":"https://github.com/angular/prophecy","last_synced_at":"2025-10-06T11:30:52.591Z","repository":{"id":15645849,"uuid":"18383002","full_name":"angular/prophecy","owner":"angular","description":"Deferred/Promise for AngularJS 2.0","archived":true,"fork":false,"pushed_at":"2014-06-20T22:01:33.000Z","size":234,"stargazers_count":36,"open_issues_count":1,"forks_count":6,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-09-26T11:03:10.831Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/angular.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-04-02T22:00:59.000Z","updated_at":"2024-02-26T17:10:30.000Z","dependencies_parsed_at":"2022-09-12T15:13:32.127Z","dependency_job_id":null,"html_url":"https://github.com/angular/prophecy","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular%2Fprophecy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular%2Fprophecy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular%2Fprophecy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/angular%2Fprophecy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/angular","download_url":"https://codeload.github.com/angular/prophecy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219877267,"owners_count":16554853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-25T11:03:13.367Z","updated_at":"2025-10-06T11:30:47.312Z","avatar_url":"https://github.com/angular.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Prophecy – Angular 2.0 Deferred/Promise\n\n## Status: In-Development\n\nThis project makes available an ES6 `Deferred` implementation, using\n[ES6 `Promises`](https://github.com/domenic/promises-unwrapping).\nAlso included is a utility mock implementation of `Promise` with a corresponding\n`PromiseBackend` which allows flushing of the `Promise`'s underlying microtask\nqueue, allowing developers to write synchronous tests against Promise-based\nlibraries.\n\n## Install\n\n`$ npm install --save angular/prophecy`\n\n## Deferred\n\nThe `Deferred` class is a small wrapper around `Promise` which lifts the\nrequirement of resolving the promise within the resolver function that gets\npassed to the `Promise` constructor.\n\nExample with vanilla `Promise`:\n```javascript\nvar promise = new Promise(function(resolve, reject) {\n  setTimeout(function() {\n    resolve('done');\n  }, 1000);\n});\npromise.then(function(val) {\n  console.log(val);\n});\n//Logs \"done\" to the console in 1 second\n```\n\nExample with `Deferred` without using PromiseMock:\n```javascript\nimport {Deferred} from './node_modules/prophecy/src/Deferred';\nvar deferred = new Deferred();\ndeferred.promise.then(function(val) {\n  console.log(val);\n});\nsetTimeout(function() {\n  deferred.resolve('done');\n}, 1000);\n//Logs \"done\" to the console in 1 secondn\n```\n\n### Deferred Instance Methods and Properties\n\n| name           | description |\n| -------------- | ----------- |\n| resolve(value) | Alias to `promise.resolve()` |\n| reject(reason) | Alias to `promise.reject()` |\n| promise        | `Promise` instance, used to chain actions to be executed upon fulfillment of the promise |\n\n## PromiseMock Module (For Testing)\n\nThe `PromiseMock` module contains two classes that allow synchronous testing of\npromise-based APIs. The `PromiseBackend` class provides methods to register and\nunregister the `PromiseMock` class as the global `Promise` constructor, as well\nas methods to flush the queue of pending operations registered by the\n`PromiseMock`. The `PromiseMock` implementation is exactly the same as the\nnative/Traceur ES6 `Promise`, except that it adds its pending tasks to the\nflushable `PromiseBackend` queue instead of a hidden microtask queue.\n\nExample test of `Deferred` using `PromiseBackend`:\n```javascript\nimport {PromiseBackend} from './node_modules/prophecy/src/PromiseMock';\nimport {Deferred} from './node_modules/prophecy/src/Deferred';\ndescribe('.resolve()', function() {\n  it('should call the resolver\\'s resolve function with the correct value',\n    function() {\n      var resolveSpy = jasmine.createSpy('resolveSpy');\n      PromiseBackend.forkZone().run(function() {\n        var deferred = new Deferred();\n        deferred.promise.then(resolveSpy);\n        deferred.resolve('Flush me!');\n        PromiseBackend.flush(true);\n      });\n\n      expect(resolveSpy).toHaveBeenCalledWith('Flush me!');\n  });\n});\n```\n\n### PromiseBackend\n\nThe `PromiseBackend` class is completely static. This\nclass manages the process of patching the global object with\n`PromiseMock` as well as flushing any pending promise fulfillment operations.\nThe PromiseBackend keeps a single queue of pending tasks, which is shared\nby all promises.\n\nThe PromiseBackend provides a convenience method to create a zone within\nwhich tests can be executed, which will automatically patch and unpatch\n`window.Promise`. The zone will also verify that no outstanding requests are\nwaiting to be flushed.\n```javascript\nbeforeEach(function() {\n  //No need for PromiseBackend.patchWithMock(), or an afterEach() to unpatch\n  this.zone = PromiseBackend.forkZone();\n});\nit('should resolve with a smiley', function() {\n  this.zone.run(function() {\n    var resolveSpy = jasmine.createSpy();\n    var backend = new PromiseBackend();\n    new Promise(function(resolve) {\n      resolve(':)');\n    }).\n    then(resolveSpy);\n    backend.flush();\n    expect(resolveSpy).toHaveBeenCalledWith(':)');\n  });\n})\n```\n\nThe `flush` method is called in lieu of waiting for the next VM turn, and\nprevents the need for writing async tests using `setTimeout`. Example writing\nan test that waits for an async operation with `setTimeout`:\n```javascript\nit('should resolve with a smiley', function(done) {\n  var resolveSpy = jasmine.createSpy();\n  new Promise(function(resolve) {\n    resolve(':)');\n  }).\n  then(resolveSpy);\n  setTimeout(function() {\n    expect(resolveSpy).toHaveBeenCalledWith(':)');\n    done();\n  }, 0);\n});\n```\n\nWith `PromiseMock` and `PromiseBackend.flush()`, this same test can be expressed\nas:\n```javascript\nit('should resolve with a smiley', function() {\n  var resolveSpy = jasmine.createSpy();\n  PromiseBackend.forkZone().run(function() {\n    new Promise(function(resolve) {\n      resolve(':)');\n    }).\n    then(resolveSpy);\n    PromiseBackend.flush(true);\n  });\n\n  expect(resolveSpy).toHaveBeenCalledWith(':)');\n});\n```\n\n####  PromiseBackend Methods and Properties\n\n| name                         | description |\n| ---------------------------- | ----------- |\n| static setGlobal(global:Object)     | global context to which the native implementation of `Promise` is attached (default: window) |\n| static flush(recursiveFlush=false)  | Flushes all tasks that have been queued for execution. If recursiveFlush is true, the backend will continue flushing until the queue is empty, including tasks that have been added since flushing began. Returns the `PromiseBackend` instance to allow chaining. |\n| static executeAsap(fn:Function)     | Add a function to the queue to be executed on the next flush |\n| static restoreNativePromise()       | Restore the native Promise implementation to the global object |\n| static patchWithMock()              | Replace the global Promise constructor with `PromiseMock` |\n| static verifyNoOutstandingTasks()   | Throw if tasks are in the queue waiting to flush |\n| static zone:forkZone()              | Creates and returns a new zone which automatically patches `window.Promise` with the PromiseMock before execution, and restores the original promise after execution. |\n| static queue:Array.\u0026lt;Function\u0026gt; | Array of functions to be executed on next flush, populated by `executeAsap()`. Note that this is undefined until an instance of `PromiseBackend` is created. |\n| global:Object                       | The global context within which `PromiseBackend` is operating, default: window |\n\n[Design Doc](https://docs.google.com/a/google.com/document/d/1ksBjyCgwuiEUGn9h2NYQGtmQkP5N9HbehMBgaxMtwfs/edit#) (superceded by implementation in this project).\n\n## TODO\n\n * Add A+ tests for PromiseMock. This implementation is copied from Traceur\n   (which is ported from V8). The Traceur implementation is already passing A+\n   tests. This project should have the tests as well.\n * Add src/index.js to export items that should be available at runtime.\n * Add build process\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangular%2Fprophecy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fangular%2Fprophecy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fangular%2Fprophecy/lists"}