ajayvohra2005/hack-promises 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

ajayvohra2005/hack-promises

Composer 安装命令:

composer require ajayvohra2005/hack-promises

包简介

Promises/A+ implementation in Hack language

README 文档

README

This project provides Promises/A+ implementation in Hack.

Overview

Key features

  • Promises have synchronous wait and cancel methods.
  • Works with any object that implements HackPromises\ThenableInterface
  • Support for Hack HH\KeyedIterator, and Hack Generator.

Requirements

HHVM 4.128 and above.

Installation

  • Git clone this repository

  • Install composer

  • In the root directory of this repository, run the command

      composer install
    

To use this package,

    composer require ajayvohra2005/hack-promises

Running tests

After installation, run the following command in the root directory of this repository:

    ./vendor/bin/hacktest tests/

License

This project is made available under the MIT License (MIT). Please see LICENSE file in this project for more information.

Tutorial

A promise represents the result of the resolution of an asynchronous operation, and the side-effects associated with the resolution.

Resolving a promise

Resolving a promise means that a promise is either fulfilled with a value or rejected with a reason. Resolving a promises triggers callbacks registered with the promises's then method. These callbacks are triggered only once and in the order in which they were added. When a callback is triggered, it is added to a global task queue. When the global task queue is run, the tasks on the queue are removed and executed in the order they were added to the queue.

Global task queue

The global task queue can be run as needed, or in an event loop. By default, the global task queue is run implicitly once prior to the program shutdown. The global task queue can be run explictily as shown below:

  HackPromises\TaskQueue::globalTaskQueue()->run();

Callbacks

Callbacks are registered with a promise by calling the then method of the promise, and by providing optional $onFulfilled and $onRejected functions, whereby the functions must be of type HackPromises\ThenCallback.

When you register callbacks with a promise by calling the then method, it always returns a new promise. This can be used to create a chain of promises. The next promise in the chain is invoked with the resolved value of the previous promise in the chain. A promise in the chain is fulfilled only when the previous promise has been fulfilled.

Quick example

Below we show a quick start example that illustrates the concepts discussed so far:

use namespace HackPromises;
use type HackPromises\Promise;

<<__EntryPoint>>
function quick_start_example(): void {
  require_once(__DIR__.'/../vendor/autoload.hack');
  \Facebook\AutoloadMap\initialize();

  $promise = new Promise();

  $promise
    ->then((mixed $value): mixed ==> {
        // Return a value and don't break the chain
        return "Hello, " . ($value as string);
    })
    // This then is executed after the first then and receives the value
    // returned from the first then.
    ->then((mixed $value): void ==> {
        $msg = $value as string;
        echo "{$msg}\n";
    });

  // Resolving the promise triggers the callback, and outputs 'Hello, reader.'.
  // The callbacks are executed on the global task queue, prior to program shutdown
  $promise->resolve('reader.');
  
}

Promise rejection

When a promise is rejected, the $onRejected callbacks are invoked with the rejection reason, as shown in the example below:

use type HackPromises\Promise;

<<__EntryPoint>>
function promise_rejection_example(): void {
  require_once(__DIR__.'/../vendor/autoload.hack');
  \Facebook\AutoloadMap\initialize();

    $promise = new Promise();
    $promise
        ->then(null, (mixed $reason): void ==> {
            $msg = $reason as string;
            echo "{$msg}\n";
        });

    // Outputs "Error!"
    $promise->reject('Error!');
}

Rejection forwarding

If an exception is thrown in an $onRejected callback, subsequent $onRejected callbacks are invoked with the thrown exception as the reason.

use type HackPromises\{Promise, RejectedPromise};

<<__EntryPoint>>
function rejection_forwarding_example(): void {
  require_once(__DIR__.'/../vendor/autoload.hack');
  \Facebook\AutoloadMap\initialize();

    $promise = new Promise();
    $promise
        ->then(null, (mixed $reason): mixed ==> {
            return new RejectedPromise($reason);
        })
        ->then(null, (mixed $reason): void ==> {
        });

    // Outputs nothing
    $promise->reject('No Error!');
}

If an exception is not thrown in a $onRejected callback and the callback does not return a rejected promise, downstream $onFulfilled callbacks are invoked using the value returned from the $onRejected callback, as shown in the example below:

use namespace HackPromises as P;

<<__EntryPoint>>
function ignore_rejection_example(): void 
{
  require_once(__DIR__.'/../vendor/autoload.hack');
  \Facebook\AutoloadMap\initialize();
  
  $promise = new P\Promise();
  $promise ->then(null, (mixed $reason): mixed ==> {
        return "It's ok";
    })->then( (mixed $value): void ==> {
        echo $value as string;
    });

  // Outputs 'It's ok'
  $promise->reject('Error!');
}

Synchronous wait

You can resolve a promise synchronously by caling the wait method on a promise.

Calling the wait method of a promise invokes the wait function provided to the promise, and implicitly runs the global task queue. An example showing the use of the wait method is shown below:

use namespace HackPromises;

use type HackPromises\Promise;
use type HackPromises\ResolveCallback;

<<__EntryPoint>>
function promise_wait_function_example(): void {
  require_once(__DIR__.'/../vendor/autoload.hack');
  \Facebook\AutoloadMap\initialize();

  $wait_fn = (ResolveCallback $cb) ==> {
    $cb('reader.');
  };

  $promise = new Promise($wait_fn);

  $promise
    ->then((mixed $value): mixed ==> {
        // Return a value and don't break the chain
        return "Hello, " . ($value as string);
    })
    // This then is executed after the first then and receives the value
    // returned from the first then.
    ->then((mixed $value): void ==> {
        $msg = $value as string;
        echo "{$msg}\n";
    });

  // Calling wait  resolves promise synchronously and outputs 'Hello, reader.'.
  $promise->wait();
}

If an exception is encountered while invoking the wait function of a promise, the promise is rejected with the exception and the exception is thrown. Calling wait method of a promise that has been fulfilled will not trigger the wait function. It will simply return the previously resolved value

Calling wait method on a promise that has been rejected will throw an exception. If the rejection reason is an instance of \Exception the reason is thrown. Otherwise, a HackPromises\RejectionException is thrown and the reason can be obtained by calling the getReason method of the exception.

Unwrapping a promise

When you call the wait method without an argument, or with the argument true, it unwraps the promiose. Unwrapping the promise returns the value of the promise if it was fulfilled, or throws an exception if the promise was rejected. You can force a promise to resolve but not unwrap by passing false to the wait method of the promise, as shown in the example below:

$promise = new Promise();
$promise->reject('foo');
// This will not throw an exception. It simply ensures the promise has
// been resolved.
$promise->wait(false);

When unwrapping a promise, the resolved value of the promise will be waited upon until the unwrapped value is not a promise. This means that if you resolve promise A with a promise B and unwrap promise A, the value returned by the wait function will be the result of resolving promise B, as shown in the example below;

use namespace HackPromises as P;

<<__EntryPoint>>
function unwrapping_example(): void 
{
  require_once(__DIR__.'/../vendor/autoload.hack');
  \Facebook\AutoloadMap\initialize();
  
  $b = new P\Promise();
  $a = new P\Promise( (P\ResolveCallback $cb): void ==> { $cb($b);});
  $b->resolve('foo');
  $result = $a->wait() as string;

  // Outputs 'foo'
  echo $result;
}

Synchronous cancel

You can cancel a promise that has not yet been fulfilled synchronously using the cancel() method of a promise.

API classes

Promise

For the base case, you can use Promise class to create a promise.

If you want to resolve the promise asynchronosuly and invoke the registerd then callbacks, you can create the Promise without any arguments to the constructor.

If you want be able to synchronously resolve or cancel the Promise , pass the wait and cancel functions to the constructor.

Wait function

The wait function must be of type HackPromises\WaitFunction. The wait function provided to a Promise constructor is invoked when the wait method of the Promise is called. The wait function must resolve the Promise by calling the HackPromises\ResolveCallback function passed to it as an argument, or throw an exception.

Cancel function

When creating a Promise you can provide an optional cancel function of type HackPromises\CancelFunction, which is invoked by the promise if you call the cancel() method of the promise. The cancel function may optionally reject the promise by invoking the HashPromises\RejectCallback function passed to it as an argument.

FulfilledPromise

The FulfilledPromise class object is fulfilled on construction.

RejectedPromise

The RejectedPromise class object is rejected on construction.

IteratorPromise

The IteratorPromise class creates an aggregated promise that iterates over an iterator of promises, or values, and triggers callback functions in the process. Use Create::iterFor to create an iterator for a vec<mixed> or a dict<arraykey, mixed>.

GeneratorPromise

The GeneratorPromise class wraps a generator that yields values, or promises.

Create

The Create class provides helper methods.

Acknowledgements

This project is inspired by Guzzle Promises. However, it has signficant differences in API and implementation, owing to the language and best-practices requirements of Hack.

ajayvohra2005/hack-promises 适用场景与选型建议

ajayvohra2005/hack-promises 是一款 基于 Hack 开发的 Composer 扩展包,目前已累计 13 次下载、GitHub Stars 达 0, 最近一次更新时间为 2021 年 10 月 16 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「hack」 「promises」 「hacklang」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 ajayvohra2005/hack-promises 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 ajayvohra2005/hack-promises 我们能提供哪些服务?
定制开发 / 二次开发

基于 ajayvohra2005/hack-promises 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 13
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: Hack

其他信息

  • 授权协议: MIT
  • 更新时间: 2021-10-16