Thursday, September 27, 2018

javascript - Promise how to implement in this situation?



i have a problem with sync using fs.readfile, they are not inicializing at the first time, if i try request again, then i have results. I know i can use promise and i find something useful with Q from Kriskowal.
I tried it but without success. I didn´t understand very well how to implement it. If someone can help with this, i will be eternally grateful.




code:



  "use strict"

var Q = require('q');
var fs = require('fs');
var arrayZipBand = [];
var jsonZipCode = [];
var arrayParsedZipcodeBr = [];


exports.parse = function(opts) {

if (opts.zipBand.constructor != Array) {
opts.zipBand = [opts.zipBand];
}
if (opts.location.constructor != Array) {
opts.location = [opts.location];
}

if (opts.config === 0) {

opts.zipBand.forEach(function(file) {
fs.readFile(file, 'utf8', function(err, logData) {
if (err) throw err;
let text = logData.toString();
decodeURIComponent(text);

let lines = text.split('\n');

lines.forEach(function(line) {
let parts = line.split('@');


if (parts[1] != undefined) {
let obJson = {
LOC_NU: parts[0],
LOC_CEP_INI: parts[1],
LOC_CEP_FIM: parts[2]

}
arrayZipBand.push(obJson);
}


});


});

});

opts.location.forEach(function(file) {
fs.readFile(file, 'utf8', function(err, logData) {



if (err) throw err;

let text = logData.toString();
decodeURIComponent(text);

let lines = text.split('\n');

lines.forEach(function(line) {

let parts = line.split('@');

if (parts[1] != undefined) {
for (let i = 0; i < arrayZipBand.length; i++) {
if (parts[0] == arrayZipBand[i].LOC_NU) {
jsonZipCode.push(arrayZipBand[i]);
}
}
if (jsonZipCode === undefined) {
throw "Was not possible to find Zipcode for the id " + parts[0];

}

for (let i = 0; i < jsonZipCode.length; i++) {
let obJson = {
LOC_NU: parts[0],
UFE_SG: parts[1],
LOC_NO: parts[2],
MUN_NU: parts[8],
LOC_CEP_INI: jsonZipCode[i].LOC_CEP_INI,
LOC_CEP_FIM: jsonZipCode[i].LOC_CEP_FIM

}

arrayParsedZipcodeBr.push(obJson);
}
jsonZipCode = [];

}


});

});
});



};
return arrayParsedZipcodeBr;

}


Answer



uhm it seems you are trying to read files in the loop cycle then, but in a async way. First question, is why async reading those files? You can always read them in sync way:



var data=fs.readFileSync(fname, encoding);


By the way, if you wish to read them async and keep the for...loop you need something like a Promise, or a timed wait or a more complex synchronization mechanism.



You can keep it simple, without using any other packages/modules in this way:




/**
* Promise.All
* @param items Array of objects
* @param block Function block(item,index,resolve,reject)
* @param done Function Success block
* @param fail Function Failure block
* @example

promiseAll(["a","b","c"],
function(item,index,resolve,reject) {

MyApp.call(item,function(result) {
resolve(result);
},
function( error ) { reject(error); }):
},
function(result) { // aggregated results

},function(error) { // error

})


* @author Loreto Parisi (loretoparisi at gmail dot com)
*/
promiseAll: function(items, block, done, fail) {
var self = this;
var promises = [],
index = 0;
items.forEach(function(item) {
promises.push(function(item, i) {
return new Promise(function(resolve, reject) {

if (block) {
block.apply(this, [item, index, resolve, reject]);
}
});
}(item, ++index))
});
Promise.all(promises).then(function AcceptHandler(results) {
if (done) done(results);
}, function ErrorHandler(error) {
if (fail) fail(error);

});
}, //promiseAll


so you can call it like



promiseAll(arrayOfItems, function(item, index, resolve, reject) {
// do something on item
if (someSuccessCondOnThisItem) {
resolve(item)

} else {
reject(new Error("operation failed"))
}
}, function(results) { // aggregated results

console.log("All done %d", results.length);

}, function(error) { // error
console.log(error.toString());
});



Keep in mind that this is a very simplified approach, but in most of cases it works when cycling through arrays.



Here is a simple working example in the playground:





var console = {
log : function(s) { document.getElementById("console").innerHTML+=s+"
"}

}
var promiseAll= function(items, block, done, fail) {
var self = this;
var promises = [],
index = 0;
items.forEach(function(item) {
promises.push(function(item, i) {
return new Promise(function(resolve, reject) {
if (block) {
block.apply(this, [item, index, resolve, reject]);

}
});
}(item, ++index))
});
Promise.all(promises).then(function AcceptHandler(results) {
if (done) done(results);
}, function ErrorHandler(error) {
if (fail) fail(error);
});
}; //promiseAll


arr=[1,2,3]
promiseAll(arr
,function(item,index,resolve,reject) {
console.log("Resolving item[" + index+"]")
var okCond=true
if(okCond) {resolve(item)} else { reject(new Error("item[" + index+"]")) }
}
,function(results) { // aggregated results
console.log("All done of "+results.length);

}
,function(error) { // error
console.log(error);
});






Finally, a complete asynchronous example, showing how to defer execution of a XMLHttpRequest, when cycling through a list. The ExecutionBlock is calling reject and resolve after the SimpleRequest responds, causing the Promise the wait its execution before calling the then.






var console = {
log: function(s) {
document.getElementById("console").innerHTML += s + "
"
}
}
// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest

SimpleRequest = {
call: function(what, response) {
var request;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {

request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
// state changes
request.onreadystatechange = function() {
if (request.readyState === 4) { // done
if (request.status === 200) { // complete
response(request.responseText)
} else response();

}
}
request.open('GET', what, true);
request.send(null);
}
}
//PromiseAll
var promiseAll = function(items, block, done, fail) {
var self = this;
var promises = [],

index = 0;
items.forEach(function(item) {
promises.push(function(item, i) {
return new Promise(function(resolve, reject) {
if (block) {
block.apply(this, [item, index, resolve, reject]);
}
});
}(item, ++index))
});

Promise.all(promises).then(function AcceptHandler(results) {
if (done) done(results);
}, function ErrorHandler(error) {
if (fail) fail(error);
});
}; //promiseAll

// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject) {
SimpleRequest.call('https://icanhazip.com/', function(result) {

if (result) {
console.log("Response[" + index + "] " + result);
resolve(result);
} else {
reject(new Error("call error"));
}
})
}

arr = [1, 2, 3]

promiseAll(arr, function(item, index, resolve, reject) {
console.log("Making request [" + index + "]")
ExecutionBlock(item, index, resolve, reject);
}, function(results) { // aggregated results
console.log("All response received " + results.length);
console.log(JSON.stringify(results));
}, function(error) { // error
console.log(error);
});






No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...