Promise proces one by one (Sequential) - promise

function one_by_one(objects_array, iterator, callback) {
var start_promise = objects_array.reduce(function (prom, object) {
return prom.then(function () {
return iterator(object);
});
}, Promise.resolve()); // initial
if(callback){
start_promise.then(callback);
}else{
return start_promise;
}
}
one_by_one(requestBodyAll,task);
I tried the above code but it processed only the first file. Can someone help please?
requestBodyAll - contains the files list to process.
task - function returns promise.

Looks about right. If the reduction is not progressing past the first file, then it's likely that task(first_file) throws. You can find out by logging errors.
Also, you're better off returning a promise from one_by_one and not passing a callback.
function one_by_one(objects_array, work) {
return objects_array.reduce(function (prom, object) {
return prom.then(function() {
return work(object);
});
}, Promise.resolve()); // initial
}
one_by_one(requestBodyAll, someWorkFn)
.then(task)
.catch(function(error) {
console.log(error);
});
one_by_one() will (as in the question) deliver the result of iterator(last_file) as an argument to task. You may prefer to pass nothing, in which case write :
.then(function() {
return task();
})
You could immunize the process against errors by catching inside one_by_one().

Related

How to wait for function with subscribe to finish in angular 8?

I want to wait for one function to finish before executing the function next to it.
I have one function called getData() in which http call occurs which returns an observable. The second function checkDuplicate() we have subscribed to that function getData() . and we have third function called proceed() in which we call the checkDuplicate() function and once the checkDuplicate() function is completed, we are calling alert("finished"). But the issue here is even before checkDuplicate() function is completed, alert has been triggered.
find the code for better clarification:
getData(): Observable<any>{
return this.http.get<any>(URL...);
}
checkDuplicate(){
return this.getData().subscribe(response => {
if(response){
console.log("Inside");
}
});
}
proceed(){
this.checkDuplicate();
console.log("finished");
}
Actual Result
finished
Inside
Expected result
Inside
finished
I have tried asyn/await to wait for checkDuplicate() function to finish. But still no use.
It would be grateful if u share the solution.
Thanks in Advance !!!
The gotcha of async programming. Here's a solution with promises (you can also use observables):
getData(): Observable<any>{
return this.http.get<any>(URL...);
}
async checkDuplicate(){
var response = await this.getData().toPromise();
if (response) {
console.log("Inside");
}
}
async proceed(){
await this.checkDuplicate();
console.log("finished");
}
You can update something like this.
getData(): Observable<any>{
return this.http.get<any>(URL...);
}
checkDuplicate() {
return Promise(resolve=>{
this.getData().subscribe(response => {
if(response){
console.log("Inside");
}
resolve(true);
});
});
}
proceed(){
this.checkDuplicate().then(value=>{
console.log("Return from promise => "+ value);
console.log("finished");
});
}
You can return promise from checkDuplicate and call another function after it is resolved by using "then".

How to get the data from BehaviorSubject after its completed?

I have a function that returns a BehaviorSubject but when I try to use the data I get back from the function I need to use it once all the data is back, is there a way to know when the BehaviorSubject is done pulling all the data?
I tried using .finally but it never gets called. Here is the code I'm using.
getData() {
let guideList = '';
this.getChildren(event.node)
.subscribe(
function(data) {
console.log('here');
guideList = data.join(',');
},
function(err) {
console.log('error');
},
function() {
console.log('done');
console.log(guideList);
}
);
}
getChildren(node: TreeNode) {
const nodeIds$ = new BehaviorSubject([]);
//doForAll is a promise
node.doForAll((data) => {
nodeIds$.next(nodeIds$.getValue().concat(data.id));
});
return nodeIds$;
}
Attached is a screen shot of the console.log
Easiest way is to just collect all the data in the array and only call next once the data is all collected. Even better: don't use a subject at all. It is very rare that one ever needs to create a subject. Often people use Subjects when instead they should be using a more streamlined observable factory method or operator:
getChildren(node: TreeNode) {
return Observable.defer(() => {
const result = [];
return node.doForAll(d => result.push(d.id)).then(() => result);
});
}

.then is not a function Angularjs factory

I just started learning Jasmine test cases for angularjs. I am unable to test below code.Kindly help
$scope.getConstants = function(lovName) {
ConstantService.getConstants(lovName).then(function(d) {
switch (lovName) {
case 'WORKFLOW':
$scope.workflowTypes = d;
$scope.loadCounterpartyTmp();
break;
--------Other Cases
}
My ConstantService is defined as
App.factory('ConstantService', [ '$http', '$q', function($http, $q) {
return {
getConstants : function(lovName) {
return $http.post('/sdwt/data/getConstants/', lovName).then(function(response) {
return response.data;
}, function(errResponse) {
return $q.reject(errResponse);
});
}
I want to test getConstants function.I need to create a mock of ConstantService and pass the data to it.
I have written below test case but the test case is not working.Please let me know how to test the above code
describe('getConstantsForMurexEntity', function() {
it('testing getConstantsForMurexEntity function', function() {
var d=[];
d.push(
{id:1,value:'ABC'},
{id:2,value:'DEF'},
{id:3,value:'IJK'},
{id:4,value:'XYZ'},
);
//defined controller
spyOn(ConstantService, 'getConstants').and.returnValue(d);
$scope.getConstants('WORKFLOW');
expect($scope.workflowTypes).toBe(d);
The above test case is not working as it is saying "ConstantService.getConstants(...).then is not a function".
Your ConstantService.getConstants() function returns a promise, which your actual code is using, with the .then() call. This means means that when you spy on it, you also need to return a promise, which you are not doing. Because you are not returning a promise, when your actual call tries to call .then(), it is undefined, which is the reason for the error message.
Also, you aren't using Array.push correctly.
Your test should probably look something like the following (note, this is untested):
describe('getConstantsForMurexEntity', function() {
it('should set workflowTypes to the resolved value when lovName is "WORKFLOW"', inject(function($q) {
var deferred = $q.defer();
spyOn(ConstantService, 'getConstants').and.returnValue(deferred.promise);
var d = [
{id:1,value:'ABC'},
{id:2,value:'DEF'},
{id:3,value:'IJK'},
{id:4,value:'XYZ'},
];
$scope.getConstants('WORKFLOW');
deferred.resolve(d);
$scope.$apply();
expect($scope.workflowTypes).toBe(d);
}));
});

Moving a promise from it() function to beforeEach()

I am writing some BDD unit tests for the first time and I'd like to eliminate some repeated code for one of my test suites. The following async unit test code works fine, but I'd like to set up the Promise in the beforeEach() block somehow, since I will be writing many more it() tests, and each one will need to run the db.find(...) call. Thanks
describe('DB retrieve row', function() {
beforeEach(function () {
// i'd like to set up the promise in this block
});
it("returns a least one result", function () {
function success(orderData) {
// keep the following line in this it() block
expect(orderData.length).to.be.ok;
}
function fail(error) {
new Error(error);
}
return db.find('P9GV8CIL').then(success).catch(fail);
});
});
Simply something like this would work
describe('DB retrieve row', function() {
var promise;
beforeEach(function () {
promise = db.find('P9GV8CIL')
});
it("returns a least one result", function () {
function success(orderData) {
// keep the following line in this it() block
expect(orderData.length).to.be.ok;
}
function fail(error) {
new Error(error);
}
return promise.then(success).catch(fail);
});
});

Simple chain of promisified function wrapper?

For example A is an existing object with API following node.js convention:
function A() {
}
A.prototype.op = function (cb) {
cb(undefined, 'success');
};
A.prototype.op2 = function (cb) {
cb(undefined, 'success 2');
};
A.prototype.log = function(r) {
console.log(r);
};
When I do Promise.promisifyAll(A.prototype) I will get generated *Async() functions.
I would like to have a readable chain like this:
Promise.bind(a)
.then(a.opAsync)
.then(a.op2Async)
.then(a.log);
I know that this doesn't work because we need additional function wrapper returning promise:
Promise.bind(a).then(function() {
return this.opAsync();
}).then(function(){
return this.op2Async();
}).then(function(r) {
this.log(r);
});
Do I have to write wrapper for every promisified function? Or there is a better way to design this API?
Adding a dummy parameter to original function resolved the problem.
A.prototype.op2 = function (x, cb) {
cb(undefined, 'success 2');
};
Working example
Issue with details

Resources