I have a this:
new Promise(function (resolve, reject)
{
return Promise.mapSeries(array, function(field)
{
var objCb = {};
var params = {};
objCb.ok = function () {};
objCb.send = function (data)
{
errors.push(data.message);
};
objCb.negociate = function (err)
{
errors.push(data.message);
};
theFunction(params, objCb);
}
}
I have test multiple solutions, but don't work:
return Promise.promisify(theFunction(params, objCb), {multiArgs: true});
and
return Promise.fromCallback(function (objCb)
{
return theFunction(params, objCb);
}, {multiArgs: true}).spread(function (a)
{
console.log("==== 1");
console.log(a);
});
If you have a solution to wait a callback or convert into promise (without edit the function (theFunction)) in a mapSeries, I would be delighted to learn it.
Thanks in advance.
Promise.mapSeries returns a promise, so you don't need to re-wrap it.
Promise.mapSeries(array, function(field)
{
return new Promise( function(resolve, reject)
{
var objCb = {};
var params = {};
objCb.ok = function (resolve()) {};
objCb.send = function (data)
{
reject(data.message);
};
objCb.negociate = function (err)
{
reject(data.message);
};
theFunction(params, objCb);
}
}
Note: mapSeries will stop on the first error it encounters.
Related
I am trying to write a function that returns an array of two objects, which is a promise. The original is rather lengthy so I try to abbreviate it:
function initCalc() {
var [av, driving] = calcCarRoute(start, end, dt)
var results = [];
results.push(av);
results.push(driving);
return results;
};
function calcCarRoute(start, end, dt) {
var temp = new Promise(function(resolve, reject) {
var driving = {};
var directionsService = new google.maps.DirectionsService();
var request = {
//some code;
};
directionsService.route(request, function(result, status) {
if (status == 'OK') {
//some code;
resolve(driving);
};
});
});
return temp.then(function(value) {
var driving = value;
//some code;
return driving;
}).then(function(value2) {
var AV = {};
//some code;
return Promise.all([AV, value2]);
})
};
However, when executing, I get the error:
calcCarRoute is not a function or its return value is not iterable . I feel more or less certain that the problem is with the fact that I want the return value to be an array, because my structurally identical functions that return an object works fine. I have also tried returning just [AV, value2] instead of Promise.all() in calCarRoute but that did not work either.
EDIT: to entertain some reasonable comments, I have developed a toy model. The goal of the codes below is to save the returned values of calcFood() in two promises, so that I can chain them for further manipulation later on.
initCalc();
function initCalc() {
var [staple, meat] = calcFood().then(function([value1, value2]) {
return [value1, value2];
});
var other = calcOther();
Promise.all([staple, meat, other]).then(function([staple, meat, other]){
for (i=0; i<4; i++){
console.log(JSON.stringify(staple));
console.log(JSON.stringify(meat));
console.log(JSON.stringify(other));
}
})
};
function calcFood() {
var temp = new Promise(function(resolve, reject) {
resolve({Lunch:'Rice', Dinner:'Pasta'});
});
return temp.then(function(value) {
var meat = {};
Object.assign(meat, value);
meat.Lunch = 'Fish';
meat.Lunch = 'Chicken';
return [value, meat];
})
};
function calcOther() {
var temp = new Promise(function(resolve, reject) {
resolve({Other:'None'});
});
return temp;
};
First of all, I can't find a suitable title for this question - please feel free to edit.
I have the following function that reads objects from indexDb,
loadNeededParcels = property => {
const dbResults = [];
var readTransaction = this.db
.transaction("parcelData")
.objectStore("parcelData");
readTransaction.openCursor().onerror = e => {
console.log("open cursor error ", e);
};
readTransaction.openCursor().onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
dbResults.push(cursor.value);
cursor.continue();
} else {
return dbResults;
}
};
};
Now when I call this function with a simple function call, for example:
console.log(loadNeededParcels('hasData'))
The console log is undefined. I am guessing this happens because the function does not wait for the cursor to finish and return the dbResults variable?
So my question is this - how can I re-write this function as a promise, or rather to wait for the readTransaction.openCursor().onsucess to trigger?
So the expected result is for the function to actually return the values read from the database before exiting.
I am using cursors since the .getAll() the method is not supported in IE.
A simple solution that I ended up using:
loadNeededParcels = property => {
return new Promise((resolve, reject) => {
var readTransaction = this.db
.transaction("parcelData")
.objectStore("parcelData");
readTransaction.openCursor().onerror = e => {
reject(e);
};
const dbResults = [];
readTransaction.openCursor().onsuccess = e => {
const cursor = e.target.result;
if (cursor) {
dbResults.push(cursor.value);
cursor.continue();
} else {
resolve(dbResults);
}
};
});
};
Try something like this. Do not call openCursor twice, that creates two requests.
function loadNeededParcels(db, property) {
return new Promise(function(resolve, reject) {
var results = [];
var tx = db.transaction('parcelData');
tx.onerror = function(event) {
reject(tx.error);
};
var store = tx.objectStore('parcelData');
// Open a cursor over all items
var request = store.openCursor();
request.onsuccess = function(event) {
var cursor = request.result;
if(cursor) {
var value = cursor.value;
if(value) {
// Only append defined values to the array
results.push(cursor.value);
}
cursor.continue();
} else {
resolve(results);
}
};
});
}
loadNeededParcels(db, 'hasData').then(function(results) {
console.log('Results', results);
}).catch(function(error) {
console.error(error);
});
Suppose I have a function called log which simply prints the given string.
Can I refactor my code so both of these function could work?
log("needsChange").doSomethingWithTheStringBeforePrintingIt();
log("perfectStringToPrint");
You can do something similar with nested class logics:
var log = (function() {
//Class
var _log = (function() {
function _log(message) {
this.message = message;
}
_log.prototype.doSomethingWithTheStringBeforePrintingIt = function() {
this.message = this.message.split("").reverse().join("");
return this;
};
_log.prototype.capitalizeFirstWord = function() {
this.message = this.message[0].toUpperCase() + this.message.substr(1);
return this;
};
_log.prototype.print = function() {
return this.message;
};
return _log;
}());
//Instancer function
return function log(message) {
//Return instance of class
return new _log(message);
};
})();
//Test
console.log(log("needsChange")
.doSomethingWithTheStringBeforePrintingIt()
.capitalizeFirstWord()
.print(), log("perfectStringToPrint")
.print());
If you are comfortable with promises, then you can do something like this:
var logger = (function() {
//Class
var _log = (function() {
function _log(message) {
var _this = this;
this.message = message;
this.promise = null;
this.promises = [];
this.promise = Promise.all(this.promises).then(function(values) {
console.log(_this.message); // [3, 1337, "foo"]
});
}
_log.prototype.reverse = function() {
var self = this;
this.promises.push(new Promise(function(resolve, reject) {
setTimeout(resolve, 0, (function() {
self.message = self.message.split("").reverse().join("");
})());
}));
return this;
};
_log.prototype.capitalizeFirst = function() {
var self = this;
this.promises.push(new Promise(function(resolve, reject) {
setTimeout(resolve, 0, (function() {
self.message = self.message[0].toUpperCase() + self.message.substr(1);
})());
}));
return this;
};
return _log;
}());
//Instancer function
return function log(message) {
//Return instance of class
return new _log(message);
};
})();
//Test
logger("needsChange").reverse().capitalizeFirst().reverse(); //Capitalizes last letter
logger("perfectStringToPrint");
This removes the need for a .print call.
I have made a library to solve this issue
https://github.com/omidh28/clarifyjs
I suspect this is very trivial but I have this code:
var latestMth;
d3.csv("data/blah.csv", function(rows) {
x = rows.map(function(d) {
return parseDate(d.dt)
});
latestMth = formatDateOutputMTH(d3.max(d3.values(x)));
});
...
...
.text("Month is " + latestMth);
It works ok displaying "Month is Mar17".
I've attempted to make the above a function but the result now comes through as "Month is undefined". Why is this happening:
var latestMth = function() {
d3.csv("data/blah.csv", function(rows) {
x = rows.map(function(d) {
return parseDate(d.dt)
});
return formatDateOutputMTH(d3.max(d3.values(x)));
});
}
...
...
.text("Month is " + latestMth());
Assuming d3.csv() is not async.
Because you don't return from your function:
var latestMth = function() {
return d3.csv("data/blah.csv", function(rows) { // added return
x = rows.map(function(d) {
return parseDate(d.dt)
});
return formatDateOutputMTH(d3.max(d3.values(x)));
});
}
Note, if it's async, you can use a Promise:
function setLatestMonth() {
return new Promise((resolve, reject) => {
d3.csv("data/blah.csv", function(rows) {
x = rows.map(function(d) {
return parseDate(d.dt)
});
resolve(formatDateOutputMTH(d3.max(d3.values(x))));
});
});
}
setLatestMonth().then(latestMonth => {
// ...
// ...
// ...
.text("Month is " + latestMonth);
});
I don't know d3.csv() - if it already returns a promise, you can simply chain that one instead of creating a new Promise by yourself.
How to pass data from promise then method to an object method.
this.httpReq(url).then(function (data) {
this.storeData(data);
});
I know that here I'm out of scope and this doesn't refer to my object. But, nevertheless, I can't understand how to resolve it.
Bellow you can find entire code snippet. In the end, I want to get data from the service API and store it in the object array property this.storage.
var http = require('http');
function CoubApi (url) {
this.url = url;
this.storage = [];
this.httpReq = httpReq;
this.searchData = searchData;
this.storeData = storeData;
}
function httpReq (url) {
var promise = new Promise (function (resolve, reject) {
http.get(url, function (res) {
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
if(data.length > 0) {
resolve(JSON.parse(data));
} else {
reject("Error: HTTP request rejected!");
}
});
}).on('error', function (err) {
console.log("Error: ", e);
});
});
return promise;
}
function storeData (data) {
var i;
console.log("Storrrreee");
for(i = 0; i < 10; i++) {
this.storage.push(data.coubs[i]);
}
}
function searchData (searchtext, order, page) {
var url = this.url+
"search?q="+searchtext+
"&order_by="+order+
"&page="+page;
this.httpReq(url).then(function (data) {
this.storeData(data);
});
}
var coub = new CoubApi("http://coub.com/api/v2/");
coub.searchData("cat", "newest_popular", 1);
console.log(coub.storage);
You can store this in varaible:
var self = this;
this.httpReq(url).then(function (data) {
self.storeData(data);
});
or use bind:
this.httpReq(url).then(function (data) {
this.storeData(data);
}.bind(this));