Promisifying Callbacks in Node.js [duplicate] - javascript

This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Closed 6 years ago.
I have this node js app working with several callback functions which I am trying to promisify to no avail.
Its getting to the point where I dont know if it is even possible. If you can help me promisify the code below I'll probably be able to do the rest of it:
var i2c_htu21d = require('htu21d-i2c');
var htu21df = new i2c_htu21d();
htu21df.readTemperature(function (temp) {
console.log('Temperature, C:', temp);
});
Any insight helps!!!

The common pattern is:
<promisified> = function() {
return new Promise(function(resolve, reject) {
<callbackFunction>(function (err, result) {
if (err)
reject(err);
else
resolve(result);
});
});
}
For your specific example (to which you might want to add error handling):
readTemperature = function() {
return new Promise(function(resolve) {
htu21df.readTemperature(function (temp) {
resolve(temp);
});
});
}
readTemperature().then(function(temp) {
console.log('Temperature, C:', temp);
});

You need to use bluebird for this.
var bluebird = require('bluebird');
var i2c_htu21d = require('htu21d-i2c');
var htu21df = new i2c_htu21d();
var readTemperature = bluebird.promisify(htu21df.readTemperature);
readTemperature().then((temp) => {console.log('Temperature, C:', temp);});

Related

Javascript promise not waiting to resolve before then [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 2 years ago.
I'm writing javascript code to parse a huge file (several GBs) and I'm using FileReader's readAsArrayBuffer function with promises (see below):
function readRaw(fc, length) {
const fileReader = new FileReader();
return new Promise((resolve, reject) => {
fileReader.onloadend = function(value) {
console.log("onloadend");
fc.offset += length;
resolve(new Uint8Array(value.result));
}
fileReader.onerror = (err) => {
console.error(err);
reject(err);
}
const slice = fc.handle.slice(fc.offset, fc.offset + length);
fileReader.readAsArrayBuffer(slice);
});
}
function parsefile(file) {
let fc = { handle: file, offset: 0 };
let buffer = {};
var promise = readRaw(fc, 32);
promise.then(function(value) {
console.log("success: offset=" + fc.offset)
buffer = value
}).catch((e) => {
console.error(e);
});
console.log("offset=" + fc.offset);
}
document
.getElementById('fileToRead')
.addEventListener('change', function () {
let file = this.files[0];
if (file) {
parsefile(file);
}
}, false);
My expectation is that Promise.prototype.then() should wait for the promise to resolve before continuing but I'm not able to get it to work no matter how I tweak the code or switch to use async/await.
Expected:
onloadend
success: offset=32
offset=32
Actual
offset=0
onloadend
success: offset=32
Thanks in advance for any help and enlightenment!
Per Why await beats Promise.then(...)"
The fundamental difference between await and vanilla promises is that await X() suspends execution of the current function, while promise.then(X) continues execution of the current function after adding the X call to the callback chain.

How to store the result object of a query into an object variable in nodejs [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 4 years ago.
I am using this query to select all records from the products table and I want to store them inside an object variable which later I can use it for other purposes, so I tried this
var SelectQuery = "Select * FROM `products`";
var ProductDetails = {};
conn.query(SelectQuery, function (err, result) {
if(err) {
console.log(err);
} else {
ProductDetails = result;
}
});
console.log(ProductDetails);
But in Console I get this {}.
(Thanks to user jfriend00 for pointing out a major oversight in my original answer)
If conn.query is returning a promise then you could make this work in the manner you are describing by using async/await:
async function getProducts() {
var SelectQuery = "Select * FROM `products`";
var ProductDetails = {};
await conn.query(SelectQuery, function(err, result) {
if (err) {
console.log(err);
} else {
ProductDetails = result;
}
});
console.log(ProductDetails);
}
But note this only works if your conn.query returns a promise. Also, it is a newer ES feature, so you may need to transpile it depending on your node version. Also, note that the function this takes place in will need to be wrapped with async.
Otherwise, the other candidates to leverage for handling asynchronicity are callback functions and Promises.
If conn.query does not return a promise, you could write your own query implementation that would return a promise so you could leverage async/await:
function asyncQuery(sqlQuery) {
return new Promise((resolve, reject) => {
conn.query(SelectQuery, function(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
})
})
}
Then the original function could be rewritten as:
async function getProducts() {
var SelectQuery = "Select * FROM `products`";
var ProductDetails = await asyncQuery(SelectQuery);
console.log(ProductDetails);
}

Nightmare Promises with for..loop api calls, waterfall & anti-pattern (Bluebird.js) [duplicate]

This question already has answers here:
How can I sequentially chain promises using bluebirdjs?
(2 answers)
Closed 6 years ago.
I am struggling with many aspects when dealing with Promises after promises, API calls inside For..Loops and my guess is that I'm developing promises anti-patterns.
This exact codepen illustrates my issue with Promises:
http://codepen.io/ghuroo/pen/EZWoGQ?editors=0010
Code sample:
$('#start').on('click', function() {
log('here we go: ');
promise1().then(function(success) {
log(success);
promise2().then(function(success) {
log(success);
promise3().then(function(success) {
log(success);
}).catch(function(error) { log(error); });
}).catch(function(error) { log(error); });
}).catch(function(error) { log(error); });
});
Any help on how to improve my code?
As you can see, I can't get the for..loop to log in the right order, it seems like it never resolves..
Also, any tips on how to prevent the waterfall thing? (I would like to print the error only once, instead of one for each promise call)
Edit:
For anyone looking for the solution, here's #jaromanda-x's solution: http://codepen.io/ghuroo/pen/pReLZm?editors=0010
For your promise3
function promise3() {
// NOTE: this function returns a function
function delay(value) {
return function() {
return new Promise(function(resolve) {
setTimeout(resolve, 500, value);
});
}
}
log('promise 3 started (takes 4*500ms = 2 seconds)');
var p = Promise.resolve();
for (i = 0; i < 4; i++) {
p = p.then(delay(i)).then(function(n) {
log('promise 3 - iteration nr. ' + n);
})
}
return p.then(function() {
return '<b>i\'m done 3</b>';
});
};
I usually write them more like this:
promise1()
.then(function (success) {
log(success);
return promise2();
})
.then(function (success) {
log(success);
return promise3();
})
.then(function (success) {
log(success);
})
.catch(function (error) {
log(error);
});

getting async nodejs value from each callback calls [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
var async = require('async');
var square = function (id, callback) {
Business.prototype.getBusinessUser(id,function(userObject){
return callback(userObject);
});
};
async.eachSeries(findBusinessResult, function (businessObject, callback) {
//console.log("results from square");
var result = square(businessObject["id"] , function(result){
console.log(result);
});
callback(); // Alternatively: callback(new Error());
}, function (err,results) {
if (err) { throw err; }
console.log('Well done :-)!');
console.log(results);
});
Why does the result always become undefined: any help please.
async is reserved word in ES7 and might give you problem later, when it's implemented.
What you might want to consider is actually using async/await togheter with babel.
Some browser is starting to implement it already
var square = id =>
new Promise(rs =>
Business.prototype.getBusinessUser(id, rs)
)
async search() {
for (let businessObject of findBusinessResult) {
let result = await square(businessObject.id)
console.log(result)
}
}
I hope this will be a game changer solution for most ppl. This is making ASYC java callback into somthing which look like sync with effiecent callback handling. Its my three days of challange. [Callbacks][1] are indeed a a major challage in javacript and here is how to solve issue using promises .
install bluebird
npm install bluebird --save
//inyour code
var Promise = require('bluebird'); //yeah awsome bird indeed :)
function extendBusinessObjectPromise(id,element) {
return new Promise(function(resolve, reject) {
Business.prototype.getBusinessUser( id ,function(userObject){
var extend = require('util')._extend;
mergedJson = userObject;
elements = element;
extend({},elements);
extend(elements,mergedJson);
global.businesssWithUsers.push(elements); //sahred object
resolve(global.businesssWithUsers)
})
})
}
//NOW how do you i call the promise result inside a foreach loop and get its value returned as callback result. seem crazy idea :(
Person.prototype.getPersons = function(filter , callback) {
//this my own Bill count since i have one using one user account
global.businesssWithUsers = [];
models.PersonModel.findAll(filter_combined).then(function (findBusinessResult) {
global.businesssWithUsers = []
var extend = require('util')._extend;
var mergedJsonArray = [];
if (findBusinessResult==null) {
return callback(false,"no result found");
}
var promiseBusinessResult = null; //promise reslover :)
var findBusinessResult =JSON.parse(JSON.stringify(findBusinessResult));
findBusinessResult.forEach(function(eachElement) {
var id = element["userId"];
promiseBusinessResult = extendBusinessObjectPromise(id,element);
});
promiseBusinessResult.done(function(result){
callback(true,result); //pass the result to main function
});
}).catch(function (err) {
log.error(err["errors"][0]["message"])
callback(false,err["errors"][0]["message"])
return
})
}
Success at last. Cheers!

Angular2: Returning Promise [duplicate]

This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Closed 6 years ago.
I am using Angular2 for my application and I have to consume Amazon S3 javascript sdk for browser.
I have the following function:
getBuckets() {
var s3 = this.getS3();
var params = {};
s3.listBuckets(params, function(err, response) {
if (err) {
// What to return?
}
else {
// What to return?
}
})
}
s3.listBuckets is the javascript API from Amazon for S3. It is expecting a call back function. But the caller of getBuckets is expecting a Promise. How should I change the above getBuckets(), such that the caller of getBuckets(), will look like:
getBuckets().then(
...
)
Thanks in advance.
If you are using TypeScript you can do something like this to return a promise. I can imagine it would be around the same in the JavaScript style:
getBuckets() {
return new Promise(function (resolve, reject) {
var s3 = this.getS3();
var params = {};
s3.listBuckets(params, function(err, response) {
if (err) {
reject(err);
}
else {
resolve(response);
}
})
})
}
The AWS SDK for JavaScript has supported promises since version 2.3.0 released March 31st. Here's the annoucement.
I suggest you update to the latest SDK version if you are using something earlier than 2.3.0, and then use promises instead of callbacks.
You can use $q, documentatie here: https://docs.angularjs.org/api/ng/service/$q
That would look something like this:
getBuckets() {
var deferred = $q.defer();
var s3 = this.getS3();
var params = {};
s3.listBuckets(params, function(err, response) {
if (err) {
deferred.reject(err);
}
else {
deferred.resolve(response);
}
})
return deferred.promise;
}
you can create your own promise like this:
var myPromiseFunction = function(iserr){
var deferred = $q.defer();
var myreturnvalue = 'somevalue';
if(iserr === true){
deferred.reject('some error');
}else{
deferred.resolve(myreturnvalue);
}
return deferred.promise;
}
And call it like this:
var throwerror = false;
//or var throwerror = true; if you want to create an error
myPromiseFunction(throwerror).then(function(res){
console.log(res);
}).catch(function(err){
console.log(err);
})
This way you can create promises (they don't even have to be async but it would not have any purpose for non-async operations.

Categories

Resources