0
votes

I'm updating Observable code from RXJS 5 to 6.

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'
import { AppConfig } from '../config/app-config';
import { Xapi } from 'x-lib';
import { ClicksActive, ClicksBalance } from '../models/user.model';
import { getLambdaErrorMessage } from "../helpers/lambda-error.helper";
import { map } from 'rxjs/operators';
import { catchError } from 'rxjs/operators';


@Injectable(
    { providedIn: 'root' }
)
export class ClicksService {

    constructor() {
    }

    requestActive(
        idNumber: String
    ): Observable<ClicksActive> {

        let parameters =
        {
            apiUsername: this.getApiUsername(),
            apiPassword: this.getApiPassword(),
            apiBaseUrl: this.getApiBaseUrl(),
            idNumber: idNumber
        }

        return Xapi.addTransaction('clicksActive', parameters, { timeout: AppConfig.OTP_REQUEST_TIMEOUT, queue: false })
        .pipe(map(res => {
            let response = res.data;
            let clicksActive: ClicksActive = this.parseActiveResponse(response);
            return clicksActive;
        }), catchError((error) => {
            let errorMessage = getLambdaErrorMessage(error);
            let clicksActive: ClicksActive = {
                success: false,
                active: false,
                errorMessage: errorMessage
            }

            return Observable.of(clicksActive);
        })
        )
    }

    parseActiveResponse(response): ClicksActive {
        let clicksActive: ClicksActive = {
            success: response.success,
            active: response.active,
            errorMessage: response.errorMessage
        }
        return clicksActive;
    }

...

For reference, Xapi looks like this:

import { ApiTransactions } from "./api.model";
export declare class Xapi {
    private static transactions;
    private static timeoutCheckInterval;
    constructor();
    /**
     * Add transaction to be processed
     *
     * @param {string} lambda
     * @param {object} request
     * @param opts
     * @returns {Observable<any>}
     */
    addTransaction(lambda: string, request: object, opts?: any): Observable<any>;
    /**
     * Get all transactions
     *
     * @returns {ApiTransactions}
     */
    static getTransactions(): ApiTransactions;
    /**
     * Process transaction response
     *
     * When the transaction comes back from the lambdas, process it.
     *
     * @param rx
     */
    static transactionResponse(rx: any): void;
    /**
     * Process transaction that is not queued
     *
     * @param {string} pid
     */
    static processTransaction(pid: string): void;
    /**
     * Checks timeouts on transactions
     */
    private static checkTimeouts();
    /**
     *  Starts interval check for timeouts
     */
    private static startTimeoutCheck();
    /**
     * Stops interval for timeout check
     */
    private static stopTimeoutCheck();
}
export declare let Xapi: Xapi;

This in turn calls clicksActive.js - which is just an ajax request:

class ClicksActive {

    constructor(api, config, log, dbi) {

        this.dbi = dbi;
        this.log = log;

        this.apiUsername = '';
        this.apiPassword = '';
        this.apiBaseUrl = '';
        this.apiTokenExpiration = 3500;
    }

    request(tx) {
        this.apiUsername = tx.apiUsername;
        this.apiPassword = tx.apiPassword;
        this.apiBaseUrl = tx.apiBaseUrl;
        var _this = this;
        this.dbi.apiUsers.find({ username: this.apiUsername })
            .then(
                function(result) {
                    if (result.length === 0) {
                        _this.requestFromApiWithNewToken(tx, false);
                    } else {
                        var user = result[0];
                        var now = new Date();
                        now = Math.round(now.getTime() / 1000);
                        if (now >= user.expiration) {
                            _this.requestFromApiWithNewToken(tx, true);
                        } else {
                            _this.requestFromApi(tx, user.token);
                        }
                    }
                }
            ).catch();

    }

    requestFromApiWithNewToken(tx, update) {
        var https = require('https');
        var _this = this;

        var data = JSON.stringify({
            username: this.apiUsername,
            password: this.apiPassword
        });

        var options = {
            host: this.apiBaseUrl,
            port: 443,
            path: '/api/Authentication/Token',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': data.length
            }
        };

        var req = https.request(options, function(res) {
            res.setEncoding('utf8');
            var response = '';
            res.on('data', function(data) {
                response += data;
            });

            res.on('end', function() {
                response = JSON.parse(response);
                if (update === false) {
                    _this.saveToken(_this.apiUsername, _this.apiPassword, response.access_token);
                } else {
                    _this.updateToken(_this.apiUsername, _this.apiPassword, response.access_token);
                }
                _this.requestFromApi(tx, response.access_token);
            });
        }).write(data);
    }

    requestFromApi(tx, token) {
        var https = require('https');
        var data = JSON.stringify({
            idNumber: tx.idNumber
        });

        var options = {
            host: this.apiBaseUrl,
            port: 443,
            path: '/api/Clicks/Active',
            method: 'POST',
            headers: {
                authorization: 'Bearer ' + token,
                'Content-Type': 'application/json',
                'Content-Length': data.length
            }
        };

        https.request(options, function(res) {
            res.setEncoding('utf8');
            var response = '';
            res.on('data', function(data) {
                response += data;
            });
            res.on('end', function() {
                response = JSON.parse(response);
                if (response instanceof Array) {
                    tx.resolve(response);
                } else {
                    var responseArray = [];
                    responseArray.push(response);
                    tx.resolve(responseArray);
                }
            });
        }).on('error', function(e) {
            tx.reject([]);
        }).write(data);
    }

   

    updateToken(username, password, token) {
        var now = new Date();
        var expirationTime = Math.round(now.getTime() / 1000) + this.apiTokenExpiration;

        this.dbi.apiUsers.update({ username: username }, { $set: { token: token } });
        this.dbi.apiUsers.update({ username: username }, { $set: { expiration: expirationTime } });
    }
}

//The following binds the Lambda to the Xapi Lambda Agent to commence receiving transactions
require('./at/lambda').bind(ClicksActive);

But unfortunately I can't get it to work even though I have wrapped map into pipe.

return Xapi.addTransaction('clicksActive', parameters, { timeout: AppConfig.OTP_REQUEST_TIMEOUT, queue: false })
        .pipe(map(res => {
            let response = res.data;
            let clicksActive: ClicksActive = this.parseActiveResponse(response);
            return clicksActive;
        })

Error is:

Argument of type 'OperatorFunction<any, ClicksActive>' is not assignable to parameter of type 'UnaryFunction<Observable, Observable>'. Types of parameters 'source' and 'source' are incompatible.

I'm using RXJS 6 and Angular 11, Ionic 5.

Any advice pointing me in right direction would be so helpful.

1
Try creating a minimal reproducible example: stackoverflow.com/help/minimal-reproducible-example to try to help you out, maybe on stackblitz - bjdose

1 Answers

0
votes

TL; DR

Try below changes

change the line return Observable.of(clicksActive); to return of(clicksActive);

Remember to add the necessary import

import { of } from 'rxjs'

In rxjs v 6+ we use the static operator of See of documentation