I'm adapting a library that uses callback to use Promises. It's working when I use then(), but it doesn't work when I use await.
> dbc.solve
[AsyncFunction]
> await dbc.solve(img)
await dbc.solve(img)
^^^^^
SyntaxError: await is only valid in async function
The code for dbc.solve is:
module.exports = DeathByCaptcha = (function() {
function DeathByCaptcha(username, password, endpoint) {
...
}
DeathByCaptcha.prototype.solve = async function(img) {
return new Promise(
function(resolve, reject) {
...
}
);
};
})();
I believe this has something with the fact solve is member of prototype, but I couldn't find any information about it. I found that node didn't always supported async await for class methods, so I upgraded from node 7, now I'm using node 9.4.0.
You don't read that error message right: the problem isn't the function you're calling but the function you're in.
You may do
(async function(){
await dbc.solve(img);
// more code here or the await is useless
})();
Note that this trick should soon enough not be needed anymore in node's REPL: https://github.com/nodejs/node/issues/13209
SyntaxError: await is only valid in async function - just like the error tells you, you may only use await inside a function which is marked as async. So you cannot use the await keyword anywhere else.
https://basarat.gitbooks.io/typescript/docs/async-await.html
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html
examples:
function test() {
await myOtherFunction() // NOT working
}
async function test() {
await myOtherFunction() //working
}
You can also make anonymous callback functions async:
myMethod().then(async () => {
await myAsyncCall()
})
The await operator can only be used in an async function.
You may not need async await abstraction really. Why don't you just simply promisify dbc.solve() function with a promisifier like;
function promisify(f){
return data => new Promise((v,x) => f(data, (err, id, sol) => err ? x(err) : v({i:id, s:solution})));
}
You will have a promisified version of your dbc.solve() and if it doesn't fire an error you will be returned with an object like {i:id, s: solution} at it's then stage.
Related
I am building an app in node.js ,
i want to call a async function in users.js file which is defined inside middleware/index.js file , i have defined the function in index.js and wrapped it into an object ( for some reason) and exported that object:
function defination in middleware/index.js:
middlewareObj.getPostsHomePage = async function(obj){
await getPostsHomePageTrending(obj, getPostsHomePagePopular);
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
console.log(obj)
return obj;
}
module.exports = middlewareObj;
users.js :
const middlewareObj = require("../middleware/index.js");
await middlewareObj.getPostsHomePage(obj);
on running the code i am getting error:
await getPostsHomePage(obj);
^^^^^
SyntaxError: await is only valid in async function
What is the reason for this error and how can i solve it?
await keyword can only by used within an async function:
async function() {
await getPostsHomePage(obj);
}
You can also use promises, if you don't need to use async function:
getPostsHomePage(obj).then(result => {
console.log(result); // Do your stuff here later
})
In the following code I wrote to get data from an API, I am getting promises as an output instead of data. What am I missing? Can someone please help?
const axios = require('axios');
const ageFinder = async (userName) => {
try {
let userDetails =await axios.get(`https://hacker-news.firebaseio.com/v0/user/${userName}.json`)
let user =userDetails.data
return user
} catch(err) {
console.log(err.message)
}
}
console.log(ageFinder("someUser"))
As per the MDN page on async functions, any function declared async returns a promise, which resolves whatever the function returns or rejects with an error, if any is encountered within the function (see "Return Value" section of page linked above).
So you will need to put your function call ageFinder("someUser") in another async function and await its result before logging, or you may use .then().
An async function always returns a promise. To use it you need to await it in another async function. If you do not want to await in another async function you may use it with the alternative then method. For example:
ageFinder("someUser")
.then((response) => {
console.log(response);
}).
.catch((err) => {
console.log(err);
});
First things first, I made sure to write a quick demo of the issue I'm talking about here https://codesandbox.io/s/exciting-swirles-7cs3s
But essentially, using the isomorphic-fetch library, I'm running into an issue where I can't really get the value, or you might say, resolution, of the fetch() function.
import fetch from "isomorphic-fetch";
async function test() {
return await fetch("https://google.com", { mode: "no-cors" });
}
let t = test();
console.log(t);
The outcome of which is
Now I've also considered the other way of using fetch() like this
fetch("https://google.com", { mode: "no-cors" })
.then(response => response.text())
.then(data => console.log(data));
which actually delivers a string, but I prefer doing it the first way, if possible? It's also very possible I'm not using fetch correctly.
Try it like this:
import fetch from "isomorphic-fetch";
async function test() {
const response = await fetch("https://google.com", { mode: "no-cors" });
return response.text();
}
async function main() {
let t = await test();
console.log(t);
}
main();
You need to await the promise, and that means you need an async function.
fetch will return a promise, not a string. In your second example you call .text() on it. You will have to do something similar in asyc/await
Use t.then(res => console.log(res)); it will return response object.
As you have async function test and you are not awaiting it like await test() so it will return promise.
As per your comment you should be using await test(). But you can only use await inside async so I suggest to use wrapper function like below.
import fetch from "isomorphic-fetch";
async function test() {
return await fetch("https://google.com", { mode: "no-cors" });
}
async function wrapper() {
let t = await test();
console.log(t.text());
}
wrapper();
Let's say I have a simple Node.js app that has these methods in another file:
module.exports = {
completeQuest(data) {
// Code here
},
killMonster(data) {
// Also code here
},
};
And they are not AJAX commands. These just manipulate some data within the app. I'd export as such in allActions.js:
const player = require('./playerActions');
module.exports = {
player,
};
and of course later, in main JS file const actions = require('./allActions');
So, generally, I'd do:
actions.player.killMonster();
actions.player.completeQuest();
But I want them to act one after the other. I know I can do async/await, but I'm not doing any AJAX calls, so would a Promise still be the best way?
What about using a yield function? Would that be good? I'm looking for opinions is all. Thank you.
I'm going to assume that killMonster and completeQuest perform asynchronous actions. (You've said they're "not ajax", but your question suggests they're not synchronous, either.)
Yes, this is a use case for promises, either explicit promises or those provided by async functions. Have killMonster and completeQuest return a promise (either by doing so explicitly or making them async functions), and then either:
actions.player.killMonster()
.then(
() => actions.player.completeQuest()
)
.catch(error => {
// Handle error
});
or, within an async function:
try {
await actions.player.killMonster();
await actions.player.completeQuest();
} catch (error) {
// Handle error
}
Here's a simple async/await example using setTimeout to provide the asynchronous part:
const delay = (ms, ...args) =>
new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
// Stand-ins for the actions
const player = {
actions: {
async killMonster() {
await delay(500, "monster killed");
},
async completeQuest() {
await delay(800, "quest complete");
}
}
};
// Top-leve async function (see my answer here:
// https://stackoverflow.com/questions/46515764/how-can-i-use-async-await-at-the-top-level
(async () => {
try {
console.log("Killing monster...");
await player.actions.killMonster();
console.log("Monster killed; completing question...");
await player.actions.killMonster();
console.log("Quest complete");
} catch (e) {
// Deal with error (probably don't just dump it to the console like this does)
console.error(e);
}
})();
i'm struggling with promises in a service worker while using async/await syntax.
Following situation: I got a push notification and want to handle the click event. If i use the "old" syntax with then and catch i can iteratore over the list of clients and do something with it. If i use my prefered way with async/await it wouldn't do anything.
self.addEventListener("notificationclick", event => {
// is working
event.waitUntil(self.clients.matchAll().then(clientList => {
console.log(clientList);
}));
// is not working
event.waitUntil(async () => {
const clientList = await self.clients.matchAll();
console.log(clientList);
});
});
Thanks to #Crice and #Keith,
waitUntil need a promise as argument instead of a function. So this is the working example in async/await style:
self.addEventListener("notificationclick", event =>
{
event.waitUntil(getClients());
});
async function getClients()
{
const clientList = await self.clients.matchAll();
console.log(clientList);
}
You can modify your original code to make an async IIFE as
// should be working now
event.waitUntil( (async () => {
const clientList = await self.clients.matchAll();
console.log(clientList);
})() );
The added ( ), will immediately invokes the async function hence the name async IIFE