I am new to React Native and coding in general. I paid for some code on upwork and am having a hard time integrating it in my program.
async pullBatch(since){
let param = {
userScreenName: '?screen_name=google',
count: "&count=5",
retweets: "&include_rts=false",
replies: "&exclude_replies=false",
trim: "&trim_user=true",
since: "&max_id=" + since
};
let twitterRest = new TwitterRest(); //create a new instance of TwitterRest Class
let batch = await twitterRest.pullTweets(param); //pull the Google TimeLine
return batch;
}
pullTimeline(){
let timeLine = []
for(i = 0; i <= 2; i++){
let currentBatch = this.pullBatch("1098740934588751900")
console.log(currentBatch);
timeLine = timeLine.concat(currentBatch);
}
console.log(timeLine);
// timeLine = currentBatch
return(timeLine)
}
I believe that when running pullTimeLine() the program is returning an array of three promises. (I have also run the code with "await" before pullBatch(), but it is erroring out telling me await is a reserved word) This means I am making two mistakes:
I am not correctly understanding promises in JS or how they are resolved.
I am incorrectly concatenating the arrays.
I am constantly trying to learn, so while I greatly appreciate suggestions for code fixes, I also really would appreciate if you'd teach me about where my lapses in understanding lies.
Thank you
Let's break it down. You seem to understand that pullBatch is an async function, and so calling it will return a promise create by the twitterRest interaction.
The problem is that your call to pullBatch inside your for loop will not resolve these promise (which seems to be what you want to do). The easiest way is to use await for currentBatch, but as you tried, you got the reserved error. Basically you just need to also make pullTimeline async like this:
async pullTimeline(){
...
Just realise that once you do this, pullTimeline is now an async function that will also return a promise. So to use this function you need to either use .then(), for example:
pullTimeline().then(timeLine => {
// do something with your timeline here
})
Or if you are using it within another async function, you can use await.
const timeLine = await pullTimeline() // must be inside async function
Basically at some point in your calling chain, you will have to resolve a promise using .then(), or disregard the top level promise by making a top level async function. For example:
async useTimeline() {
const timeLine = await pullTimeline()
// do something with your timeline
}
// call the function above, and just disregard its promise
useTimeLine()
Just don't forget to handle errors somewhere. Either use a .catch() on your top level promise, or use try / catch around any of your await calls.
Related
I am using Binance's Node.js API. It says regarding "Get open orders for a symbol", I should do:
binance.openOrders("ETHBTC", (error, openOrders, symbol) => {
console.info("openOrders("+symbol+")", openOrders);
});
To print out number of open orders, I do:
binance.openOrders("ETHBTC", (error, openOrders, symbol) => {
console.info(openOrders.length);
});
which works and the number gets printed out. However, I would need this result to be stored in a variable which can be used later by other functions. Building on SO's Javascript chat room, I do:
let OO =
(async() => {
const openOrders = await binance.openOrders(false);
return openOrders.length
})()
console.log(OO)
This however prints
Promise { <pending> }
only.
I have seen several other questions discussing Promise { <pending> } issue but I haven't been able to implement their solutions to this specific case.
How could I get number of open orders into a variable accessible by other functions?
You'll need to use either completely async approach or use callbacks.
The last block in your question shows exactly what this answer explains. Javascript doesn't wait for Promise to resolve/reject in a synchronous context. So your "async" block returned the unresolved Promise and the rest of your (synchronous) code didn't wait for it to resolve.
Example of using async functions
const getOpenOrdersCount = async () => {
const openOrders = await binance.openOrders("ETHBTC");
return openOrders.length;
};
const run = async () => {
const openOrdersCount = await getOpenOrdersCount();
console.log(openOrdersCount);
}
Note: You can use await only within async functions.
Example of using callbacks is your code. They are useful in a small scope, but in bigger scope they get messy and turn into a callback hell. So I wouldn't recommend using callbacks in a bigger scope.
binance.openOrders("ETHBTC", (error, openOrders, symbol) => {
console.info(openOrders.length);
// here goes rest of your code that needs to use the `openOrders` variable
});
How to call Async function in recursion actually I have Async method - async function getSSN(req,res,next) and inside this function block I need to call this function but when I call this method by code - return await getSSN(req,res,next) this code is not working for me in node js. Can anyone give me solution for that.?
So, you can't mix async/await with plain asynchronous callbacks. They do not work properly. Your async function getSSN() is not properly resolving when your request.get() finishes because that's just a plain asynchronous callback which the async function knows nothing about.
Instead, you need to use a promise-based request() option. Since, the request library is now deprecated and should not be used for new projects, I would suggest one of the alternatives that are all based on promises already. My favorite is the got() library, but you can look at the list of alternatives and pick the one that has a programming style you like.
In addition, your getSSN() function has a bunch of side effects (modifying higher scoped variables). This is not a good way to program, particularly for asynchronous operations because the outside world generally doesn't know when things are done and when the higher scoped variables have the values in them you want them to. You should make getSSN() return a promise that resolves to its result and then have the caller use that result to modify the higher scoped variables. Again, if you showed us the rest of the coding context here, we could suggest a better overall way to do this. Please notice here that you're just not providing enough code for us to be able to show you the best way to write this code. That should be a general lesson for stackoverflow. Err on the side of giving us more than you think and we can then often make suggestions and improvements far beyond what you even know to ask about.
Here's your function with all the ill-adivsed side effects still in it (because you haven't shown us the rest of the code) using got():
async function getSSN(next) {
const result = await got('idms.dealersocket.com/api/account/…').json();
if (count <= totalpage) {
const data = Object.assign({}, result.Data);
const len = Object.keys(data).length;
for (var i = 0; i <= len; i++) {
ssn.push(data[i].Row.Borrower1SSN);
}
count++;
}
}
Now, getSSN() will return a promise that resolves or rejects when the network request is finished.
I've been using #zzzzBov's fantastic loadScript() function to load JS libraries using Promises.
However, it becomes tedious and messy to chain together Promises for all of the loaded libraries. I'd like to switch to an async/await solution, but—since loadScript() function doesn't return the usable library objects I need—this isn't as straightforward as using .then() at a first glance.
The function returns a load Event, which I await. So my initial approach would be to just define some useless constants as the Promise returns, and then reference them in an if statement:
let loadedGlobalObject: any;
const lib1Loaded: Event = await loadScript(lib1URL);
const lib2Loaded: Event = await loadScript(lib2URL);
if (lib1Loaded && lib2Loaded) { // Makes this block dependent upon the await statements
loadedGlobalObject = (window as any).globalObject;
console.log(loadedGlobalObject);
}
Is this correct form? I don't know how to "invoke" the await statements; an if statement was my first guess. So I'm wondering if this is the best solution, or if there is a more efficient/accepted technique (I know that I could substitute the libXLoaded constants into the if statement, but I'm going for readability).
If I understand what you are trying to do - you want to await the loading of your libraries, and access the global objects only once they are loaded. What about something like this:
try {
async function loadLibs () {
const lib1Event: Event = await loadScript(lib1Url);
let loadedGlobalObject: any;
loadedGlobalObject = (window as any).globalObject;
console.log(loadedGlobalObject);
}
loadLibs();
catch (err) {
console.log('Error loading script: ', err);
}
The loadScript() function rejects if there was an error while loading the script, so you can wrap your code in a try...catch. Otherwise, it resolves and you can access it's global object.
Note that you can only call await within a function marked as async.
So it turns out I didn't understand async/await at all. I had thought that the awaited constants were reactive, and lines referencing them were run only after their Promises resolved; instead, it's just the rest of the function that waits.
For error-handling, as #dwosk answered, you can use a try-catch, although I wasn't concerned about this. As #Rezaa91 commented, I could have used an await Promise.all([]), except for that I'm loading dependencies in order. And, now that I understand await statements better and as #dwosk and #Bergi noted, I don't need to define those constants.
In summary, my modified code (with Promise.all() added for fun) looks like this:
let loadedGlobalObject: any;
await Promise.all([loadScript(dependency1), loadScript(dependency2)]);
await loadScript(library1);
// Will have been loaded by now.
loadedGlobalObject = (window as any).globalObject;
console.log(loadedGlobalObject);
I don't have any problem in this question, I am just interested in how knex.js menaged to something.
In code, you can write something like this
let search = knex.table('users').select('something')
if(params.minprice) search.where('minprice', params.minprice)
if(something) search.something()
let result = await search
It works, but I don't get how did they menage to hold query execution until await occured? If we did await, it means function was async aka returned a promise. But in javascript, promise executes as soon as function that returned it is called, it does not care is there .then() or .catch(). Should not query execution start al line 1? What is more, when I log search, it is not a promise, but some kind of object, so how can it be awaited?
Can someone provide a simple example how to achieve such a behaviour?
I'm guessing that search contains a property named then, which is a function that initiates the search and also behaves similarly to the functionality of Promise.prototype.then.
E.g.:
// define Searchable
let Searchable = function() {
this.searchParam = 'param';
};
Searchable.prototype = {
setSearchParam: function(p) { this.searchParam = p; },
initiateSearch: async function() {
// lots of fancy searching
console.log(`Searching with param "${this.searchParam}"`);
return `search based on "${this.searchParam}"`;
},
then: async function(callback) {
// initiate the search:
let searchResults = await this.initiateSearch();
// behave kind of like `Promise.prototype.then`!
return callback(searchResults);
}
};
// now work with it:
(async () => {
let searchable = new Searchable();
searchable.setSearchParam('mySearchParam');
console.log('No search performed yet!');
// Here's the fancy usage you're concerned with (it invokes `searchable.then`):
let searchResult = await searchable;
console.log('RESULT:', searchResult);
})();
Calling await on some value will attempt to call value.then as if it were a function accepting a callback argument.
Knex query builder is mutable and thenable object.
So every time you call for example search.where(...) for that query builder, its internal state changes and stores that new where clause.
Query builder being thenable means that the object has .then() method and when you call await search it is actually pretty much equivalent with await Promise.resolve(search) which first executes thenable and converts it to promise which is then resolved or an exception might occur.
Thenable objects are actually pretty important part of promise spec providing interoperability API between promises and non-promise objects.
This is my first post so I hope I do it right. This is my first exposure to promises and 3 hours in I still can't get it. Our project does not have support for Async Wait, unfortunately. I'm using pouchdb over sqlite.
this.recipes is used to display a page of recipes. It returns as empty, however the first time, and then always lags one recipe behind after each recipe is added. I am pretty sure this is because I return this.recipeBook before all the promises are completed. I realize in the code I posted the final return is dangling outside of any promise, but when I put it in a promise I get a "type void is not assignable to type any[]" error in my RecipesPage.ts.
I appreciate any support you guys can offer and am excited to learn the right way to hand this, and thank you in advance.
This is my call in RecipesPage.ts:
this.recipes = this.database.getAllRecipes();
This is the method in database.service.ts:
public getAllRecipes() {
this.recipeBook = new Array<Recipe>();
this.recipeDatabase.allDocs
({
include_docs: true,
}).then(docs => {
this.objectArray = docs.rows.map(row => {
return row.doc;
})
}).then(function (){
for (let object of this.objectArray) {
this.myRecipe = this.convertObjectToRecipe(object);
this.recipeBook.push(this.myRecipe);
}
})
return this.recipeBook;
}
You don't. There's no real way to 'unpack' a promise like this. The closest you can realistically get is polling.
Instead, return the promise and call .then on the promise where you're waiting for it. This is ultimately what async and await are doing under the hood. Make decisions in the UI to choose how to render your content before its loaded (and as its being loaded).