Using promises with streams in node.js

I’ve refactored a simple utility to use promises. It fetches a pdf from the web and saves it to disk. It should then open the file in a pdf viewer once saved to disk. The file appears on disk and is valid, the shell command opens the OSX Preview application, but a dialog pops up complaining that the file is empty.

What’s the best way to execute the shell function once the filestream has been written to disk?

// download a pdf and save to disk
// open pdf in osx preview for example
download_pdf()
  .then(function(path) {
    shell.exec('open ' + path).code !== 0);
  });

function download_pdf() {
  const path = '/local/some.pdf';
  const url = 'http://somewebsite/some.pdf';
  const stream = request(url);
  const write = stream.pipe(fs.createWriteStream(path))
  return streamToPromise(stream);
}

function streamToPromise(stream) {
  return new Promise(function(resolve, reject) {
    // resolve with location of saved file
    stream.on("end", resolve(stream.dests[0].path));
    stream.on("error", reject);
  })
}


Source: stackoverflow-javascript

Sequelize Transaction Error at Non-Sequlize, Stripe API Action

I have a sign up flow promise chain that creates multiple database records and Stripe records. Originally I had constructed this flow without transactions and can verify that the code works. However, when I decided to use transactions as a way to ensure that all records are created, I am getting hung up when my promise creates Stripe records. Unhandled rejection TypeError: Path must be a string. Received undefined is the error that I am given, but I’m not sure what it is related to within the context of that portion of the chain. Could it be a Promise related issue or Sequelize related?

In the promises current state, it gets down to console.log('About to create Stripe customer'); and then the error above appears.

Here is my Promise chain:

var organization;
var user;
var customer;

    return models.sequelize.transaction(function (t){
        console.log('About to create organization');
        return models.Organization.create({
            ...
        }, {transaction: t}).then(function(_organization){
            organization = _organization;
            console.log('About to create user');
            return models.User.create({
                ...
            }, {transaction: t}).then(function(_user){
                console.log('About to attach user to organization');
                user = _user;
                return user.setOrganizations([organization.organizationId], 
                { 
                    transaction: t
                }).then(function(){
                    console.log('About to create Stripe customer');
                    stripe.customers.create({
                        email: req.body.email,
                        metadata: {
                            ...
                        }
                    }, {transaction: t}).then(function(_customer){
                        console.log('About to create Stripe subscription');
                        customer = _customer;
                        stripe.subscriptions.create({
                            ...
                        }).then(function(subscription){
                            console.log('About to create account');
                            return models.Account.create({
                                ...
                            }, {transaction: t});
                        });
                    });
                });
            });
        });
    }).then(function(){//End Chain
            done(null, user);
    //End transaction
    }).catch(function(err){
        console.log(err);
        done(null, false, req.flash('error', err));
    });

Full Terminal output:

Executing (2b333db1-e13f-4282-9a3c-cf2c065aeb21): START TRANSACTION;
Executing (2b333db1-e13f-4282-9a3c-cf2c065aeb21): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
About to create organization
Executing (2b333db1-e13f-4282-9a3c-cf2c065aeb21): INSERT INTO "organization" ("organization_id","organization_name","admin","updated_at","created_at") VALUES (DEFAULT,'ndsjfndsf','tessspdn@te.somc','2017-04-22 17:25:42.290 -04:00','2017-04-22 17:25:42.290 -04:00') RETURNING *;
About to create user
Executing (2b333db1-e13f-4282-9a3c-cf2c065aeb21): INSERT INTO "user" ("user_id","first_name","last_name","email","password","updated_at","created_at") VALUES (DEFAULT,'Ndsf','Dns','tessspdn@te.somc','$2a$10$xhGyG4iD78HselgBUlPtFOJj604UPbq0W0YaXlfsdxnMj4xMmll8m','2017-04-22 17:25:42.611 -04:00','2017-04-22 17:25:42.611 -04:00') RETURNING *;
About to attach user to organization
Executing (2b333db1-e13f-4282-9a3c-cf2c065aeb21): SELECT "created_at", "updated_at", "user_id", "organization_id" FROM "organization_member" AS "organization_member" WHERE "organization_member"."user_id" = 62;
Executing (2b333db1-e13f-4282-9a3c-cf2c065aeb21): INSERT INTO "organization_member" ("user_id","organization_id","created_at","updated_at") VALUES (62,43,'2017-04-22 17:25:42.623 -04:00','2017-04-22 17:25:42.623 -04:00');
About to create Stripe customer
Executing (2b333db1-e13f-4282-9a3c-cf2c065aeb21): COMMIT;
Unhandled rejection TypeError: Path must be a string. Received undefined


Source: stackoverflow-javascript

RxJS Observable with asynchronous subscriber function

I’m trying to do something that feels like it should be straightforward, but is proving surprisingly difficult.

I have a function to subscribe to a RabbitMQ queue. Concretely, this is the Channel.consume function here: http://www.squaremobius.net/amqp.node/channel_api.html#channel_consume

It returns a promise which is resolved with a subscription id – which is needed to unsubscribe later – and also has a callback argument to invoke when messages are pulled off the queue.

When I want to unsubscribe from the queue, I’d need to cancel the consumer using the Channel.cancel function here: http://www.squaremobius.net/amqp.node/channel_api.html#channel_cancel. This takes the previously returned subscription id.

I want to wrap all of this stuff in an Observable that subscribes to the queue when the observable is subscribed to, and cancels the subscription when the observable is unsubscribed from. However, this is proving somewhat hard due to the ‘double-asynchronous’ nature of the calls (I mean to say that they have both a callback AND return a promise).

Ideally, the code I’d like to be able to write is:

return new Rx.Observable(async (subscriber) => {
  var consumeResult = await channel.consume(queueName, (message) => subscriber.next(message));
  return async () => {
    await channel.cancel(consumeResult.consumerTag);
  };
});

However, this isn’t possible as this constructor doesn’t support async subscriber functions or teardown logic.

I’ve not been able to figure this one out. Am I missing something here? Why is this so hard?

Cheers,
Alex


Source: stackoverflow-javascript

how to keep a reference to arguments passed in http call in angularJs

Hi i need to save a reference to an argument passed in a $http call so i can that way i can use with the corresponding response result in a subsequent $http call in promise chain .

var IncidentsPromises = [];
  for (var i = 0; i < $scope.mySelections.length; i++) {
    service_id = $scope.mySelections[i].services[0].service_object_id;
    var promis =service.createTicket($scope.mySelections[i],additional_info, incidentTicketParent)
    IncidentsPromises .push(promis)
  }
$q.all(IncidentsPromises)
  .then(function (res) {
// I need to match the number of the ticket returned 
//by the createticket() call to the serviceId that created it.
//before i can make the acknowledge call i need the service id matching the incident Id
//since the call is async i can't rely on the order of the response.

  service.acknowledge(service_id, incidentId)
    .then(function (res) {
       console.log("Incident acknowledged ")
    }, function (err) {

      $log.log("Incidents not Acknowledge");
    });
  }, function (err) {
      $log.log("tickets not created");
    });

the createTicket and acknowledge are just simple $http calls that return a promise.

Any sugestion is more than welcome . thanks in advance


Source: stackoverflow-javascript

How to create Promise, for modal confirm dialog

I am actually using Angular 2, but I found a solution, but it seems to me like it is just an workaround. And it isn’t fully working right now.

I created an service, that can be injected anywhere, and an component, that sits at root component template.

export class DialogService {
    input: {
        observer: Observer<boolean>,
        observable: Observable<boolean>
    } = {}
    output: {
        observer: Observer<DialogEvent>,
        observable: Observable<DialogEvent>
    } = {}

    constructor(){
        this.input.observable = new Observable((observer: Observer<boolean>) => {
            this.input.observer = observer
        })
        this.output.observable = new Observable((observer: Observer<DialogEvent>) => {
            this.output.observer = observer
        })
    }

    ask(question: string, cancel: string, accept: string) {
        this.output.observer.next({question, cancel, accept})
        return this.input.observable.toPromise()
    }
}
export class DialogComponent {
    constructor(private dialogService: DialogService) {
        this.dialogService.ouput.subscribe(event => this.show())
    }

    cancel() {
        this.dialogService.input.next(false)
        this.hide()
    }

    accept() {
        this.dialogService.input.next(true)
        this.hide()
    }
}

This setup works to the point, that it will open on ask in service, and close, with correct function (accept, or cancel), but the promise is not created, or fired.

Anyway, if there is a better way to make this work, I al 100% for it.


Source: stackoverflow-javascript

batch mode with promise in javascript

I need to process a lot of data. For each entry of the data, we need to submit query to mysql. my current solution is like following:

    var Q = require('q');
    function process(entry){
        ...
        var defered=Q.defer();
        connection.query(sql,defered.makeNodeResolver());
        return defered.promise;
    }
    function ProcessAll(results ) {
        var waitfor=[];
        for( var i=0;i< results.length;i++){
            waitfor.push( process(results[i]));
        }
        Q.all(waitfor).then(function(results) {
            notifySuc(results);
        },function(results){
            notifyFail(results);
        });
    }

However when the number of the data is huge, it will crash due to out of memory:

FATAL ERROR: Committing semi space failed. Allocation failed - process out of memory

 1: node::Abort() [node]
 2: 0x109624c [node]
 3: v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [node]
 5: v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
 6: v8::internal::Heap::CollectGarbage(v8::internal::GarbageCollector, char const*, char const*, v8::GCCallbackFlags) [node]

How can I break it with smaller batches? For example, we can process 1000 entries each time. After they are all one we resume the rest. How to do so with the callback functions?

In addition, can we make multiple entries get processed in parallel?


Source: stackoverflow-javascript

One button submits AJAX, another button queries result of that AJAX

This question is part of me trying to learn promises and deferreds. Suppose you have a button that submits a POST:

$("#submit").click( function() {
  $.post({...})
})

My understanding is that AJAX is itself a promise (which makes obvious sense), so what I’d like to do is, when user clicks #check, it returns the output of the AJAX once it is complete (assuming that #check can and will always be clicked only after #submit has been clicked).

I thought this was simple enough, so my initial code was:

$("#check").click(function() {
  $.when($.post({...})).done( function(data) {
    console.log("data")
  })  
})

But I realize that in this implementation, the AJAX wouldn’t start POSTing until #check is clicked. There’s no need for any #submit button and having the AJAX .post in #submit is redundant.

Is there a way to achieve what I’m doing using promises/deferreds?


Source: stackoverflow-javascript