{"id":18941224,"url":"https://github.com/reactphp/promise-stream","last_synced_at":"2025-04-04T12:07:56.057Z","repository":{"id":20236541,"uuid":"89217503","full_name":"reactphp/promise-stream","owner":"reactphp","description":"The missing link between Promise-land and Stream-land for ReactPHP.","archived":false,"fork":false,"pushed_at":"2024-02-26T08:57:56.000Z","size":107,"stargazers_count":111,"open_issues_count":1,"forks_count":13,"subscribers_count":10,"default_branch":"1.x","last_synced_at":"2024-04-13T15:56:00.186Z","etag":null,"topics":["php","promise","reactphp","stream"],"latest_commit_sha":null,"homepage":"https://reactphp.org/promise-stream/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reactphp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":["reactphp","clue","WyriHaximus"],"open_collective":"reactphp"}},"created_at":"2017-04-24T08:46:31.000Z","updated_at":"2024-03-18T13:49:32.000Z","dependencies_parsed_at":"2023-02-14T09:01:53.794Z","dependency_job_id":"260425fe-50f5-480c-bac9-e4597e1ca309","html_url":"https://github.com/reactphp/promise-stream","commit_stats":{"total_commits":78,"total_committers":10,"mean_commits":7.8,"dds":0.5897435897435898,"last_synced_commit":"5c7ec3450f558deb779742e33967d837e2db7871"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fpromise-stream","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fpromise-stream/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fpromise-stream/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Fpromise-stream/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reactphp","download_url":"https://codeload.github.com/reactphp/promise-stream/tar.gz/refs/heads/1.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247174418,"owners_count":20896078,"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":["php","promise","reactphp","stream"],"created_at":"2024-11-08T12:26:47.811Z","updated_at":"2025-04-04T12:07:56.041Z","avatar_url":"https://github.com/reactphp.png","language":"PHP","readme":"# PromiseStream\n\n[![CI status](https://github.com/reactphp/promise-stream/actions/workflows/ci.yml/badge.svg)](https://github.com/reactphp/promise-stream/actions)\n[![installs on Packagist](https://img.shields.io/packagist/dt/react/promise-stream?color=blue\u0026label=installs%20on%20Packagist)](https://packagist.org/packages/react/promise-stream)\n\nThe missing link between Promise-land and Stream-land\nfor [ReactPHP](https://reactphp.org/).\n\n**Table of Contents**\n\n* [Usage](#usage)\n    * [buffer()](#buffer)\n    * [first()](#first)\n    * [all()](#all)\n    * [unwrapReadable()](#unwrapreadable)\n    * [unwrapWritable()](#unwrapwritable)\n* [Install](#install)\n* [Tests](#tests)\n* [License](#license)\n\n## Usage\n\nThis lightweight library consists only of a few simple functions.\nAll functions reside under the `React\\Promise\\Stream` namespace.\n\nThe below examples refer to all functions with their fully-qualified names like this:\n\n```php\nReact\\Promise\\Stream\\buffer(…);\n```\n\nAs of PHP 5.6+ you can also import each required function into your code like this:\n\n```php\nuse function React\\Promise\\Stream\\buffer;\n\nbuffer(…);\n```\n\nAlternatively, you can also use an import statement similar to this:\n\n```php\nuse React\\Promise\\Stream;\n\nStream\\buffer(…);\n```\n\n### buffer()\n\nThe `buffer(ReadableStreamInterface\u003cstring\u003e $stream, ?int $maxLength = null): PromiseInterface\u003cstring\u003e` function can be used to\ncreate a `Promise` which will be fulfilled with the stream data buffer.\n\n```php\n$stream = accessSomeJsonStream();\n\nReact\\Promise\\Stream\\buffer($stream)-\u003ethen(function (string $contents) {\n    var_dump(json_decode($contents));\n});\n```\n\nThe promise will be fulfilled with a `string` of all data chunks concatenated once the stream closes.\n\nThe promise will be fulfilled with an empty `string` if the stream is already closed.\n\nThe promise will be rejected with a `RuntimeException` if the stream emits an error.\n\nThe promise will be rejected with a `RuntimeException` if it is cancelled.\n\nThe optional `$maxLength` argument defaults to no limit. In case the maximum\nlength is given and the stream emits more data before the end, the promise\nwill be rejected with an `OverflowException`.\n\n```php\n$stream = accessSomeToLargeStream();\n\nReact\\Promise\\Stream\\buffer($stream, 1024)-\u003ethen(function ($contents) {\n    var_dump(json_decode($contents));\n}, function ($error) {\n    // Reaching here when the stream buffer goes above the max size,\n    // in this example that is 1024 bytes,\n    // or when the stream emits an error.\n});\n```\n\n### first()\n\nThe `first(ReadableStreamInterface|WritableStreamInterface $stream, string $event = 'data'): PromiseInterface\u003cmixed\u003e` function can be used to\ncreate a `Promise` which will be fulfilled once the given event triggers for the first time.\n\n```php\n$stream = accessSomeJsonStream();\n\nReact\\Promise\\Stream\\first($stream)-\u003ethen(function (string $chunk) {\n    echo 'The first chunk arrived: ' . $chunk;\n});\n```\n\nThe promise will be fulfilled with a `mixed` value of whatever the first event\nemitted or `null` if the event does not pass any data.\nIf you do not pass a custom event name, then it will wait for the first \"data\"\nevent.\nFor common streams of type `ReadableStreamInterface\u003cstring\u003e`, this means it will be\nfulfilled with a `string` containing the first data chunk.\n\nThe promise will be rejected with a `RuntimeException` if the stream emits an error\n– unless you're waiting for the \"error\" event, in which case it will be fulfilled.\n\nThe promise will be rejected with a `RuntimeException` once the stream closes\n– unless you're waiting for the \"close\" event, in which case it will be fulfilled.\n\nThe promise will be rejected with a `RuntimeException` if the stream is already closed.\n\nThe promise will be rejected with a `RuntimeException` if it is cancelled.\n\n### all()\n\nThe `all(ReadableStreamInterface|WritableStreamInterface $stream, string $event = 'data'): PromiseInterface\u003carray\u003e` function can be used to\ncreate a `Promise` which will be fulfilled with an array of all the event data.\n\n```php\n$stream = accessSomeJsonStream();\n\nReact\\Promise\\Stream\\all($stream)-\u003ethen(function (array $chunks) {\n    echo 'The stream consists of ' . count($chunks) . ' chunk(s)';\n});\n```\n\nThe promise will be fulfilled with an `array` once the stream closes. The array\nwill contain whatever all events emitted or `null` values if the events do not pass any data.\nIf you do not pass a custom event name, then it will wait for all the \"data\"\nevents.\nFor common streams of type `ReadableStreamInterface\u003cstring\u003e`, this means it will be\nfulfilled with a `string[]` array containing all the data chunk.\n\nThe promise will be fulfilled with an empty `array` if the stream is already closed.\n\nThe promise will be rejected with a `RuntimeException` if the stream emits an error.\n\nThe promise will be rejected with a `RuntimeException` if it is cancelled.\n\n### unwrapReadable()\n\nThe `unwrapReadable(PromiseInterface\u003cReadableStreamInterface\u003cT\u003e\u003e $promise): ReadableStreamInterface\u003cT\u003e` function can be used to\nunwrap a `Promise` which will be fulfilled with a `ReadableStreamInterface\u003cT\u003e`.\n\nThis function returns a readable stream instance (implementing `ReadableStreamInterface\u003cT\u003e`)\nright away which acts as a proxy for the future promise resolution.\nOnce the given Promise will be fulfilled with a `ReadableStreamInterface\u003cT\u003e`, its\ndata will be piped to the output stream.\n\n```php\n//$promise = someFunctionWhichResolvesWithAStream();\n$promise = startDownloadStream($uri);\n\n$stream = React\\Promise\\Stream\\unwrapReadable($promise);\n\n$stream-\u003eon('data', function (string $data) {\n    echo $data;\n});\n\n$stream-\u003eon('end', function () {\n    echo 'DONE';\n});\n```\n\nIf the given promise is either rejected or fulfilled with anything but an\ninstance of `ReadableStreamInterface`, then the output stream will emit\nan `error` event and close:\n\n```php\n$promise = startDownloadStream($invalidUri);\n\n$stream = React\\Promise\\Stream\\unwrapReadable($promise);\n\n$stream-\u003eon('error', function (Exception $error) {\n    echo 'Error: ' . $error-\u003egetMessage();\n});\n```\n\nThe given `$promise` SHOULD be pending, i.e. it SHOULD NOT be fulfilled or rejected\nat the time of invoking this function.\nIf the given promise is already settled and does not fulfill with an instance of\n`ReadableStreamInterface`, then you will not be able to receive the `error` event.\n\nYou can `close()` the resulting stream at any time, which will either try to\n`cancel()` the pending promise or try to `close()` the underlying stream.\n\n```php\n$promise = startDownloadStream($uri);\n\n$stream = React\\Promise\\Stream\\unwrapReadable($promise);\n\n$loop-\u003eaddTimer(2.0, function () use ($stream) {\n    $stream-\u003eclose();\n});\n```\n\n### unwrapWritable()\n\nThe `unwrapWritable(PromiseInterface\u003cWritableStreamInterface\u003cT\u003e\u003e $promise): WritableStreamInterface\u003cT\u003e` function can be used to\nunwrap a `Promise` which will be fulfilled with a `WritableStreamInterface\u003cT\u003e`.\n\nThis function returns a writable stream instance (implementing `WritableStreamInterface\u003cT\u003e`)\nright away which acts as a proxy for the future promise resolution.\nAny writes to this instance will be buffered in memory for when the promise will\nbe fulfilled.\nOnce the given Promise will be fulfilled with a `WritableStreamInterface\u003cT\u003e`, any\ndata you have written to the proxy will be forwarded transparently to the inner\nstream.\n\n```php\n//$promise = someFunctionWhichResolvesWithAStream();\n$promise = startUploadStream($uri);\n\n$stream = React\\Promise\\Stream\\unwrapWritable($promise);\n\n$stream-\u003ewrite('hello');\n$stream-\u003eend('world');\n\n$stream-\u003eon('close', function () {\n    echo 'DONE';\n});\n```\n\nIf the given promise is either rejected or fulfilled with anything but an\ninstance of `WritableStreamInterface`, then the output stream will emit\nan `error` event and close:\n\n```php\n$promise = startUploadStream($invalidUri);\n\n$stream = React\\Promise\\Stream\\unwrapWritable($promise);\n\n$stream-\u003eon('error', function (Exception $error) {\n    echo 'Error: ' . $error-\u003egetMessage();\n});\n```\n\nThe given `$promise` SHOULD be pending, i.e. it SHOULD NOT be fulfilled or rejected\nat the time of invoking this function.\nIf the given promise is already settled and does not fulfill with an instance of\n`WritableStreamInterface`, then you will not be able to receive the `error` event.\n\nYou can `close()` the resulting stream at any time, which will either try to\n`cancel()` the pending promise or try to `close()` the underlying stream.\n\n```php\n$promise = startUploadStream($uri);\n\n$stream = React\\Promise\\Stream\\unwrapWritable($promise);\n\n$loop-\u003eaddTimer(2.0, function () use ($stream) {\n    $stream-\u003eclose();\n});\n```\n\n## Install\n\nThe recommended way to install this library is [through Composer](https://getcomposer.org/).\n[New to Composer?](https://getcomposer.org/doc/00-intro.md)\n\nThis project follows [SemVer](https://semver.org/).\nThis will install the latest supported version:\n\n```bash\ncomposer require react/promise-stream:^1.7\n```\n\nSee also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.\n\nThis project aims to run on any platform and thus does not require any PHP\nextensions and supports running on legacy PHP 5.3 through current PHP 8+ and\nHHVM.\nIt's *highly recommended to use the latest supported PHP version* for this project.\n\n## Tests\n\nTo run the test suite, you first need to clone this repo and then install all\ndependencies [through Composer](https://getcomposer.org/):\n\n```bash\ncomposer install\n```\n\nTo run the test suite, go to the project root and run:\n\n```bash\nvendor/bin/phpunit\n```\n\n## License\n\nMIT, see [LICENSE file](LICENSE).\n","funding_links":["https://github.com/sponsors/reactphp","https://github.com/sponsors/clue","https://github.com/sponsors/WyriHaximus","https://opencollective.com/reactphp"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactphp%2Fpromise-stream","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactphp%2Fpromise-stream","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactphp%2Fpromise-stream/lists"}