Azure Function outgoing storage queue binding not available on context - javascript

I have a really simple Azure Function with the sole purpose of taking all messages included in a blob and put those messages on a storage queue.
I'm running Functions 2.x, the function is written in JavaScript and I've registered a blob trigger and an output binding for storage queues.
The problem I'm having is that the output binding isn't available in ctx.bindings in my function. I'm using a named output binding, because I will have multiple output bindings. When I change the output binding name to $return and return my data, the messages are written to the queue as expected, but when I set a different name the binding doesn't show up in the context. I can however see the binding definition in ctx.bindingDefinitions.
I'm running the code locally with Azure Function Host, with the proper extensions installed.
My code goes like this:
import { Context } from '#azure/functions'
export async function run(ctx: Context , content: string): Promise<void> {
try {
const data = JSON.parse(content)
if (!ctx.bindings[data.queue]) {
throw new Error(`No output binding defined for queue '${data.queue}'`)
}
ctx.bindings[data.queue] = [...data.messages]
} catch (e) {
return Promise.reject(e)
}
}
And my function.json:
{
"disabled": false,
"bindings": [
{
"name": "content",
"type": "blobTrigger",
"direction": "in",
"path": "message-batches/{filename}.txt"
},
{
"type": "queue",
"direction": "out",
"name": "message",
"queueName": "message",
"connection": "AZURE_STORAGE_CONNECTION_STRING"
}
],
"scriptFile": "index.js"
}
My incoming content binding is available as ctx.bindings.content. I'm thinking I might be missing something trivial here, but what could be the reason for the binding not to show up under ctx.bindings?

The output binding is not available in Context.bindings until it's populated with content at runtime.
If we want to check the existence of output definition, turn to Context.bindingDefinitions.
let flag:boolean = false;
for (let bindingDefinition of ctx.bindingDefinitions) {
if(bindingDefinition.name == data.queue) {
flag = true;
break;
}
}
if(!flag){
throw new Error(`No output binding defined for queue '${data.queue}'`)
}

Related

where to call onPlanPurchased( ) method after it is in events.js or does it gets automatically called?

My idea is to make a wallet collection in database which I will create manually through wix velo code. After a pricing plan is purchased by the user where to do I call onPlanPurchased( ) method to add the amount in the wallet
import wixData from 'wix-data';
export function wixPaidPlans_onPlanPurchased(event) {
if (event.order.price.amount === 0) {
let orderData = {
"title": "Free plan purchased",
"data": event.order
};
wixData.insert("planEvents", orderData);
} else {
let orderData = {
"title": "Regular plan purchased",
"data": event.order
};
wixData.insert("planEvents", orderData);
}
}
The event handlers that you add to the events.js file in the backed are called automatically by Wix. So, in your case, when a plan is purchased the wixPaidPlans_onPlanPurchased() function will be called and it will receive information about the plan that was purchased in the event argument that is passed to it.
Side point: I think the event you are using is being deprecated and you should use the one from wix-pricing-plans instead.

"Uncaught ReferenceError: window is not defined" p5.js web worker

I have a javascript code where I use the web worker with the p5.js library. it wouldn't allow me to use any of p5's functions so I have to use the importScripts("p5.js") function to import the p5.js library before using any of p5's functions.
onmessage = (e)=>{
importScripts("p5.min.js")
// other scripts
}
But even then it gives me another error that said "Uncaught ReferenceError: window is not defined". I tracked it down and it seemed that p5 is unable to use the global variable named "window". I searched around the internet for a solution but so far found none. I wonder if there is a way around this. Thank you.
The issue here is that web workers run in a very isolated context where many of the standard global variables that would exist for javascript running on a website (window, document, etc) don't exist, and unfortunately p5.js cannot load without these variables. You could try shimming them with fake versions. Here's a basic example:
let loadHandlers = [];
window = {
performance: performance,
document: {
hasFocus: () => true,
createElementNS: (ns, elem) => {
console.warn(`p5.js tryied to created a DOM element '${ns}:${elem}`);
// Web Workers don't have a DOM
return {};
}
},
screen: {},
addEventListener: (e, handler) => {
if (e === "load") {
loadHandlers.push(handler);
} else {
console.warn(`p5.js tried to added an event listener for '${e}'`);
}
},
removeEventListener: () => {},
location: {
href: "about:blank",
origin: "null",
protocol: "about:",
host: "",
hostname: "",
port: "",
pathname: "blank",
search: "",
hash: ""
}
};
document = window.document;
screen = window.screen;
// Without a setup function p5.js will not declare global functions
window.setup = () => {
window.noCanvas();
window.noLoop();
};
importScripts("/p5.js");
// Initialize p5.js
for (const handler of loadHandlers) {
handler();
}
postMessage({ color: "green" });
onmessage = msg => {
if (msg.data === "getRandomColor") {
// p5.js places all of its global declarations on window
postMessage({
color: window.random([
"red",
"limegreen",
"blue",
"magenta",
"yellow",
"cyan"
])
});
}
};
This is only going to work for a limited subset of p5.js functions. Any functions that draw to the canvas are definitely not going to work. And I would be cautious about trying to pass objects back and forth (i.e. p5.Vector, p5.Color, etc) because everything sent via postMessage gets serialized and deserialized.
I've posted a working version of this example on Glitch.

How to store chrome identity api response in vuejs component

I'm passing the response from chrome identity api to the tab that will run my vue powered chrome extension. I need to store this information inside my vue instance tu use it inside a component. I've tried to assign the info to a variable using this.username but it will result in undefined in console. What's wrong with the code and what's the best way to accomplish this?
component code
<script>
import { EventBus } from '../../event-bus';
export default {
data () {
return {
socket: null,
isRegistered: false,
isConnected: false,
username: null,
message: '',
}
},
created() {
},
mounted() {
chrome.runtime.onMessage.addListener(
function(request, sender){
console.log(request);
this.username = request.name;
this.isRegistered = true;
});
EventBus.$emit('open-connection')
// the variable is undefined and also the open-connection event are not emitted?
console.log(this.username)
EventBus.$on('connected', (socket) => {
console.log(socket)
this.socket = socket;
this.isConnected = true;
console.log(this.socket.id)
})
},
methods: {
// I was using this method but the function isn't called inside mounted, result in an error :(
connect(){
//if( this.isRegistered === false){
//this.username = this.username;
//this.isRegistered = true;
//EventBus.$emit('open-connection')
//return this.username;
// }
}
// methods here
}
}
</script>
<style scoped>
</style>
The response from identity api (I will omit the fields value for privacy):
{
"id": "100xxxxxx",
"name": "xxx",
"given_name": "xxxx",
"family_name": "xxxx",
"picture": "https://lh4.googleusercontent.com/xxxxx.jpg",
"locale": "xx"
}
NB: the response object is not accessible in this way key.val
EDIT
After some debug I've finally found a solution. The response information retrived by the api isn't really an object but a JSON. I've used the JSON.parse() function to make it an object and now I'm able to access to the fields using key.value syntax.
Perhaps you could use the chrome.storage to set/get the data rather than rely on the components state.
Otherwise can you share what the console.log(request) is giving you and what the background script looks like?

How to customize controller's response with specific exits from helper?

I'm using Sails.js v1.2.2 and organizing my controllers with single file rather than action 2. Also I use helpers in my controllers.
Now when the helper triggers some exit other than success, the controller will automatically response with the specific format like
{
"cause": {
"name": "Exception",
"code": "ParameterError",
"exit": "ParameterError",
"traceRef": {},
"raw": {
"msg": "My custom message"
}
},
"isOperational": true,
"code": "ParameterError",
"exit": "ParameterError",
"traceRef": {},
"raw": {
"msg": "My custom message"
}
}
How can I custom the response data when the helper exits no-success?
I've tried custom exits in helper file, but not working.
U can use sails generator. sails generate response myCustomHandler. Check docs for custom responses.
Then just try catch helper like in example:
try {
await sails.helpers.test()
.intercept({ code: 'test' }, ()=>{ return new Error('err1') })
} catch (e) {
if (e.message === 'err1') {
return res.badRequest('Test Bad request')
} else if (e.code === 'ParameterError') {
return res.serverError('Parameter Error Message in server error')
} else {
return res.myCustomHandler('Test Custom handler')
}
This is an example with intercept u can use to do more custom stuff. Just ignore it if u don't need that. If u use actions2, then return with this statement. return this.res.myCustomHandler('Some error').
In myCustomHandler.js file, u can format error. Check this docs.

Load local JSON file into variable

I'm trying to load a .json file into a variable in javascript, but I can't get it to work. It's probably just a minor error but I can't find it.
Everything works just fine when I use static data like this:
var json = {
id: "whatever",
name: "start",
children: [{
"id": "0.9685",
"name": " contents:queue"
}, {
"id": "0.79281",
"name": " contents:mqq_error"
}
}]
}
I put everything that's in the {} in a content.json file and tried to load that into a local JavaScript variable as explained here: load json into variable.
var json = (function() {
var json = null;
$.ajax({
'async': false,
'global': false,
'url': "/content.json",
'dataType': "json",
'success': function(data) {
json = data;
}
});
return json;
})();
I ran it with the Chrome debugger and it always tells me that the value of the variable json is null. The content.json file resides in the same directory as the .js file that calls it.
What did I miss?
My solution, as answered here, is to use:
var json = require('./data.json'); //with path
The file is loaded only once, further requests use cache.
edit To avoid caching, here's the helper function from this blogpost given in the comments, using the fs module:
var readJson = (path, cb) => {
fs.readFile(require.resolve(path), (err, data) => {
if (err)
cb(err)
else
cb(null, JSON.parse(data))
})
}
For ES6/ES2015 you can import directly like:
// example.json
{
"name": "testing"
}
// ES6/ES2015
// app.js
import * as data from './example.json';
const {name} = data;
console.log(name); // output 'testing'
If you use Typescript, you may declare json module like:
// tying.d.ts
declare module "*.json" {
const value: any;
export default value;
}
Since Typescript 2.9+ you can add --resolveJsonModule compilerOptions in tsconfig.json
{
"compilerOptions": {
"target": "es5",
...
"resolveJsonModule": true,
...
},
...
}
If you pasted your object into content.json directly, it is invalid JSON. JSON keys and values must be wrapped in double quotes (" not ') unless the value is numeric, boolean, null, or composite (array or object). JSON cannot contain functions or undefined values. Below is your object as valid JSON.
{
"id": "whatever",
"name": "start",
"children": [
{
"id": "0.9685",
"name": " contents:queue"
},
{
"id": "0.79281",
"name": " contents:mqq_error"
}
]
}
You also had an extra }.
A solution without require or fs:
var json = []
fetch('./content.json').then(response => json = response.json())
The built-in node.js module fs will do it either asynchronously or synchronously depending on your needs.
You can load it using var fs = require('fs');
Asynchronous
fs.readFile('./content.json', (err, data) => {
if (err)
console.log(err);
else {
var json = JSON.parse(data);
//your code using json object
}
})
Synchronous
var json = JSON.parse(fs.readFileSync('./content.json').toString());
There are two possible problems:
AJAX is asynchronous, so json will be undefined when you return from the outer function. When the file has been loaded, the callback function will set json to some value but at that time, nobody cares anymore.
I see that you tried to fix this with 'async': false. To check whether this works, add this line to the code and check your browser's console:
console.log(['json', json]);
The path might be wrong. Use the same path that you used to load your script in the HTML document. So if your script is js/script.js, use js/content.json
Some browsers can show you which URLs they tried to access and how that went (success/error codes, HTML headers, etc). Check your browser's development tools to see what happens.
For the given json format as in file ~/my-app/src/db/abc.json:
[
{
"name":"Ankit",
"id":1
},
{
"name":"Aditi",
"id":2
},
{
"name":"Avani",
"id":3
}
]
inorder to import to .js file like ~/my-app/src/app.js:
const json = require("./db/abc.json");
class Arena extends React.Component{
render(){
return(
json.map((user)=>
{
return(
<div>{user.name}</div>
)
}
)
}
);
}
}
export default Arena;
Output:
Ankit Aditi Avani
for free JSON files to work with go to https://jsonplaceholder.typicode.com/
and to import your JSON files try this
const dataframe1=require('./users.json');
console.log(dataframe1);
Answer from future.
In 2022, we have import assertions api for import json file in js file.
import myjson from "./myjson.json" assert { type: "json" };
console.log(myjson);
Browser support: till september 2022, only chromium based browsers and safari supported.
Read more at: v8 import assertions post
To export a specific value from output.json (containing json shared on question) file to a variable say VAR :
export VAR=$(jq -r '.children.id' output.json)

Categories

Resources