I am trying to run getResponse once when a web components finishes loading. However, when I try to run this, the debounce function just acts as an async delay and runs 4 times after 5000 ms.
static get properties() {
return {
procedure: {
type: String,
observer: 'debounce'
}
}
}
debounce() {
this._debouncer = Polymer.Debouncer.debounce(this._debouncer, Polymer.Async.timeOut.after(5000), () => {
this.getResponse();
});
}
getResponse() {
console.log('get resp');
}
What is necessary to get getResponse to run once upon the loading of the element?
Are you sure you want to use a debouncer for that? you could just use the connectedCallBack to get a one Time Event
class DemoElement extends HTMLElement {
constructor() {
super();
this.callStack = 'constructor->';
}
connectedCallback() {
this.callStack += 'connectedCallback';
console.log('rendered');
fetch(this.fakeAjax()).then((response) => {
// can't do real ajax request here so we fake it... normally you would do
// something like this.innerHTML = response.text();
// not that "rendered" get console logged before "fetch done"
this.innerHTML = `
<p>${this.callStack}</p>
<p>${response.statusText}</p>
`;
console.log('fetch done');
}).catch(function(err) {
console.log(err); // Error :(
});
}
fakeAjax() {
return window.URL.createObjectURL(new Blob(['empty']));
};
}
customElements.define('demo-element', DemoElement);
<demo-element></demo-element>
If you really need to use an observer you could also set a flag this.isLoaded in your connectedCallback() and check for that in your observer code.
Related
I am trying to implement a function that waits until a certain console event is sent.
E.g. there are several console.endTime calls being done (for performance debugging) and I want to wait until the last one (identified by a specific message text ) is done.
My code kind of works but the problem is that page.on adds new event listeners each time I call my waitForEvent function. I understand why that happens, but haven't found a solution that avoids this.
Code looks like this :
function waitForEndEvent() {
return new Promise((res, rej) => {
registerConsoleEvent(page, res, rej);
});
}
function filterMessage() {
return (msg) => {
try {
if (msg.type() == 'timeEnd') {
if (msg.text().includes("final time")) {
console.log('timeEnd:', msg.text());
res();
}
}
} catch (e) {
rej(e);
}
};
}
function registerConsoleEvent(page, res, rej) {
page.on('console', filterMessage(res,rej));
}
Any hint how I could solve this issue?
You can just remove the event listener after receiving the message. You can use the page.removeListener(...) method to remove the event listener. So the code would be like this
function waitForEndEvent() {
return new Promise((res, rej) => {
registerConsoleEvent(page, res, rej);
});
}
function registerConsoleEvent(page, res, rej) {
page.on('console', function consoleListener(msg) {
try {
if (msg.type() == 'timeEnd') {
if (msg.text().includes('final time')) {
console.log('timeEnd:', msg.text());
page.removeListener('console', consoleListener);
res();
}
}
} catch (e) {
rej(e);
}
});
}
const { payload: {loginType, email, password, notification, self} } = action;
console.log("--TRY--");
Firebase.login(loginType, { email, password })
.catch(function(result) {
const message =
result && result.message ? result.message : 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
isError = true;
})
.then(function(result) {
if (isError) {
return;
}
if (!result || result.message) {
const message =
result && result.message
? result.message
: 'Sorry Some error occurs';
notification('error', message);
self.setState({
confirmLoading: false
});
} else {
self.setState({
visible: false,
confirmLoading: false
});
console.log("--RIGHT BEFORE I CHECK AUTH STATE--");
//the following does NOT fire
firebaseAuth().onAuthStateChanged(function*(user) {
console.log("THE GENERATOR RUNS");
if (user) {
console.log(user);
yield put({
type: actions.LOGIN_SUCCESS,
token: 'secret token',
profile: 'Profile'
});
yield put(push('/dashboard'));
}
else {
yield put({ type: actions.LOGIN_ERROR });
}
});
}
}); });
Hi. I'm currently working with redux saga for the first time. I've been trying to get yield put to fire in the callback of the firebaseAuth().onAuthStateChanged listener. The yield keyword won't work in a function that is not an ES6 generator, so I added an asterisk to the callback but now it won't execute at all. Would really appreciate any advice on the matter.
As you noticed, redux-saga effects can only be used within a generator function, and you cannot use a generator function as a regular function: calling a generator function only returns a special object.
The right way to approach this is to use an eventChannel: it lets you connect your saga to a source of events external to the redux ecosystem.
First create your eventChannel using the provided factory function: it hands you an emit function that you can use to emit events; then consume these events using the take effect.
import { eventChannel } from 'redux-saga';
import { cancelled, take } from 'redux-saga/effects';
// first create your eventChannel
const authEventsChannel = eventChannel( emit => {
const unsubscribe = firebaseAuth().onAuthStateChanged( user => {
emit({ user });
});
// return a function that can be used to unregister listeners when the saga is cancelled
return unsubscribe;
});
// then monitor those events in your saga
try {
while (true) {
const { user } = yield take (authEventsChannel);
// handle auth state
}
} finally {
// unregister listener if the saga was cancelled
if (yield cancelled()) authEventsChannel.close();
}
I am trying to run getResponse once when this web component loads, and then each time the procedure property changes.
However, when trying to run this debounce function, it is invoked 4 times and getResponse runs after a delay, but 4 times instead of 1.
static get properties() {
return {
procedure: {
type: String,
observer: 'getResponse'
},
timeout: {
type: Number,
value: null
}
}
}
ready() {
super.ready();
this.debounce();
}
debounce() {
console.log('debounce');
this.procedure = 'getInventoryActive';
clearTimeout(this.timeout) // Clear the timeout if it has already been set.
// This will prevent the previous task from executing if it has been less than <MILLISECONDS>
let that = this; // Make a new timeout set to go off in 800ms
this.timeout = setTimeout( () => {
that.getResponse();
}, 8000);
}
getResponse() {
// do something;
}
}
How can I achieve this behavior?
P.S. Also tried this debounce method within the ready function, and it's still invoking getResponse 4 times... (https://codepen.io/tony19/pen/vxZVwx)
debounce() {
this.procedure = 'name';
this._debouncer = Polymer.Debouncer.debounce(this._debouncer, Polymer.Async.timeOut.after(8000), () => {
this.getResponse();
});
}
I'm building a chrome app and I use Vue.js for the options page.
So I want to load settings from the chrome storage and put it into the vue data.
My problem is, that i can not access the vue compontens from inside the chrome storage callback. Every time i call it inside the callback, all vue elements are undefined.
Is there a way, to let the chrome storage cb function return a value, or give it an extra callback.
Here is my code
name: 'app',
data: function () {
return {
data []
}
},
methods: {
init: function() {
chrome.storage.sync.get('series', function (storageData) {
this.data = storageData //this is not possible, because this.data is undefined
})
});
}
},
created: function () {
this.init();
}
}
If using ES6 and transpiling (preferred approach). Note: arrow functions don't create a new context.
init: function() {
chrome.storage.sync.get('series', storageData => {
this.data = storageData
});
}
ES5 workaround:
init: function() {
var self = this;
chrome.storage.sync.get('series', function (storageData) {
self.data = storageData
});
}
I am trying to pass data to a child component and I keep getting an undefined prop. I think it may have an issue with when Im setting the state in the parent component. Should i not be using componentWillMount?
export default class AllItems extends Component {
constructor () {
super()
this.state=({ user: cookie.load('user')})
this.httpHandler = axios.create({
baseURL: 'http://localhost:3000/',
headers: {
'Authorization': this.state.user.token
}
})
}
componentWillMount() {
this.httpHandler('/products/')
.then(function (response) {
this.setState({ winks: response.data.data})
console.log(this.state.winks)
}.bind(this))
}
render() {
return (
<Winks products={this.state.winks} />
)
}
}
The problem is that your promise may not return before componentWillMount finishes and render is called. So products won't exist yet. You could do something like this:
render() {
if (this.state.winks) {
return (<Winks products={this.state.winks} />)
} else {
return (<div>No Winks yet</div>);
}
}
the problem is that you do not have an initial state for winks Since you are relying on an ajax call to set the state of winks, the ajax call will take place asynchronously and then it will execute the render function before the api call finishes causing this.state.winks to be undefined initially.
You could do something like this
render() {
let content = this.state.winks ? <Winks products={this.state.winks} /> : <div/>
return <div> {content} </div>