async await + toPromise hangs

2020-03-03 08:08发布

问题:

I'm using ngx-stripe , and the createToken returns an Observable which I've tried to convert to a promise so that I can use Async/await. However, it looks as though the promise dosen't resolve. Debugging doesn't reveal anything, and my try/Catch blocks doesn't capture any errors.

I wanted to know whether I'm using the toPromise correctly :

import {
    Elements,
    Element as StripeElement,
    ElementsOptions,
    BankAccountData,
    StripeService
} from 'ngx-stripe';

constructor(
    public stripeService: StripeService,

) {}



async next() {
    let token: any;
    let account: BankAccountData = {
        country: this.country,
        currency: this.currency,
        account_holder_name: this.first_name + " " + this.last_name,
        account_holder_type: this.type,
        account_number: account_number,
        routing_number: routing_number
    };

    console.log("--> Creating Bankaccount Token", account);

    try {
        token = await this.stripeService.createToken("bank_account", account).toPromise();
    } catch (excep) {
        console.log(excep);
    }

    console.log("-->Token Generated : ", token);
}

EDIT

Debugger - if it helps. This is the last console output:

Creating Bankaccount Token {country: "AU", currency: "aud", account_holder_name: "Someone Name", account_holder_type: "individual", account_number: "000123456", …}

*************************EDIT *********************** I'm not sure why, but the code worked when I created a stackblitz.

I then compared the libraries in stackblitz and updated my angular, rxjs, rxjs-compat to match what was in stackblitz and tried again and I was getting the same result as before.

I then removed the toPromise() and changed it to :

this.stripeService.createToken("bank_account", account).subscribe(data => {
               console.log(data);
             });

I'm not sure what is limiting what my project has compared to what's in stackblitz. I'm not sure how to work out what the problem is, and the only thing I can think of is rebuilding the project from scratch.

回答1:

Try doing .pipe(take(1)).toPromise().

See the logic on the internal code for rxjs. "Resolve" only gets called on completion (see code below). So, depending on how your observable works you may not get the resolution. The subscribe, however, will get called even if the observable is not complete, on each value emission which is why your subscribe works. "take(1)" will cause a completion, so that should call your promise.

Here is the rxjs code for that function.

Observable.prototype.toPromise = function (PromiseCtor) {
    var _this = this;
    if (!PromiseCtor) {
        if (_root.Rx && _root.Rx.config && _root.Rx.config.Promise) {
            PromiseCtor = _root.Rx.config.Promise;
        }
        else if (_root.Promise) {
            PromiseCtor = _root.Promise;
        }
    }
    if (!PromiseCtor) {
        throw new Error('no Promise impl found');
    }
    return new PromiseCtor(function (resolve, reject) {
        var value;
        _this.subscribe(function (x) { return value = x; }, function (err) { return reject(err); }, function () { return resolve(value); });
    });
};