I need to search the CouchDB based on several criteria entered in a form. Name, an array of Tags and so on. I would then need various views to index on these fields. Ultimately, all the results will be collated in data.js and provided to mustache.html. Say there are 3 views - docsByName, docsByTags, docsById.
What I don't know is, how to query all these views in query.js. Can this be done and how ?
Or should the approach be of that to write one view that makes multiple emits for each search somehow ?
Thank you.
From what you say I assume you are using Evently, so I will quote from Evently primer:
The async function is the main star, which in this case makes an Ajax request (but it can do anything it wants). Another important thing to note is that the first argument to the async function is a callback which you use to tell Evently when you are done with your asynchronous action. [...] Whatever you pass to the callback function then becomes the first item passed to the data function.
In short: put your Ajax requests in async.js.
As a side note: Evently is only one of the possible choices to write a couchapp and it is not clear if it is maintained. However it works and it is easy to rearrange the code to not use it.
EDIT: here is a sample async function (cut&paste from an old program):
function(cb, e) {
var app = $$(this).app
;
app.db.openDoc('SOMEDOCID', {
error: function(code, error, reason) {
alert("Error("+code+" "+error+"): "+reason);
}
, success: function(doc) {
app.view('SOMEVIEWNAME', {
include_docs: true
, error: function(code, error, reason) {
alert("Error("+code+" "+error+"): "+reason);
}
, success: function(resp) {
resp.doc = doc;
cb(resp);
}
});
}
});
}
Related
I want to make requests to two different APIs. I then need to organize that data. I'm using redux-promise.
Currently, I have a function, calls two other functions that do the AJAX request:
export function fetchEstimates(input) {
let firstRequest = fetchFirstRequest(input);
let secondRequest = fetchFirstRequest(input);
return {
type: FETCH_DATA,
payload: {
firstRequest: firstRequest
secondRequest: secondRequest
}
}
}
Unfortunately, by putting both requests in an object, I can't seem to access the results.
export default function(state = [], action) {
switch (action.type) {
case FETCH_DATA:
// console.log(action.firstRequest);
// console.log(action.secondRequest);
return result;
}
return state;
}
As I toggle the object in dev tools, I come to this:
[[PromiseStatus]]:"resolved"
[[PromiseValue]]:Object
I can continue to toggle the options, but I can't seem to access them in my code.
If in my payload, I just return this
payload: firstRequest
I don't have issues. But of course, I need both requests. Any ideas. What is a good approach to handle this?
If you look at the source for redux-promise, you'll see that it assumes you've provided a promise as the "payload" field in your action. You're instead providing an object with two promises as sub-fields under "payload". I'm assuming that you're really interested in having both promises resolve, and then passing both results to the reducer. You'd want to use Promise.all to create a new promise that receives the results of both original promises as an argument, then use that promise as your payload. The reducer would then receive something like: {type : "DATA_RECEIVED", payload : [response1, response2]}.
You need some sort of middleware to deal with Promises (like redux-thunk), and wrap the promises in Promise.all to wait until they're both resolved. Let me know if you need a code example.
I have a store load method which returns data via an ajax request. I can see that the data is being returned using Firebug, but my success handler is not getting called:
this.getCategoriesStore().load({params:{'id':d.data.category_id}}, {
success: function(category) {
console.log("Category: " + category.get('name'));
},
error: function(e) {
console.log(e);
}
});
I am returning a success parameter, along with the data:
{"success":true,"categories":{"id":5,"name":"Frying","section_id":2}}
Is there something missing or am I doing anything wrong?
Well I suppose you are looking for this:
store.load({
params:{'id':d.data.category_id},
scope: this,
callback: function(records, operation, success) {
if (success) {
console.log("Category: " + category.get('name'));
} else {
console.log('error');
}
}
});
It is not that obvious in the API that your additional params can be placed there too. But ExtJS often uses the config objects to wrap things up.
Edit to answer comment:
The short answer is: Yes
Now the longer version:
In case of the store it is up to you to directly provide anonymous (or concrete) callbacks or register events. Both will work the same in your situation here.
But you can only have one callback while you can have many events. In further scenarios you will find situations where events fits much better or where events are the only way at all. That will always be the case when you are listening. Here are some notes on that:
make use of the { single: true } property when you just need a callback once. Example: store.on('load', function(s) { /* do something*/ }, scope, { single: true }) The listener will be removed after it was called. This is needed cause of the use of a anonymous function, that cannot be removed.
make use of mon() in most cases where you bind listeners directly in class-definitions to ensure the listeners get destroyed along with the instance of the class.
Both will save you browser memory.
Try this:
store.load({
scope: this,
callback: function(records, operation, success) {
// the operation object
// contains all of the details of the load operation
console.log(records);
}
});
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Store-method-load according to the docs there is no success and error callback.
Another alternative to providing callback you can also add a "load" event listener on the store for the same effect.
This is relevant for either client or server side apps using backbone. I am attempting to create a validation function with uniqueness checks to MongoDB or some REST call (depending on environment). Both of these calls are async by nature; however, I think I actually need to make it block here for validation purposes. If I don't return anything the validate function will assume validation passed.
My code currently looks like this on the server side:
isUnique: function (key) {
var dfdFindOne = this.findOne({key: this.get(key)}),
dfd = new Deferred();
dfdFindOne.done(function (err, result) {
console.log(result);
dfd.resolve(true);
});
return dfd;
};
... some stuff here....
I feel like I can do some sort of wait till done functionality here before I return... perhaps not though. I wish backbone provided a callback function or something or accepted some sort of deferred type thing.
validate: function() {
var result = undefined;
if(!this.isUnique(key).done(function(){
result = "AHHH not unique!";
});
return result;
}
A possible solution might be to force mongodb's native node client to call things synchronously. I think I can do the same with rest calls... This is probably a bad solution though.
You could call the ajax request and set async:false in this way the return will have value. However to use async:false is evil because could appear as the browser is locked. For server side maybe there are not always workarounds for set async: false
My recommendation is to use your own validation flow instead of Backbone.validate flow, because the validation flow of Backbone was made thinking for synchronous validations only. You could try something like this:
//Code in your Model
isUnique: function (callback) {
var dfdFindOne = this.findOne({key: this.get(key)});
dfdFindOne.done(function (err, result) {
console.log(result);
callback(result);
});
};
validate: function(callback) {
this.isUnique(callback);
}
//trying to validate before save
model.validate(function(result){
if( result == 'whatexpected'){
model.save();
}
});
Ajax and Reflection
I am developing an ajax-based application and wondering, what role reflection plays or might play here?
Probably most importantly I am asking myself, if it would be a good approach to
handle all ajax responses through a single handler,
reflect or interpret the data or error
delegate further processing (e.g. where to inject the html) based upon the analysis.
Is this a budding procedure? What pros and cons come to mind?
Additional clearification
My current implementation, which I am not happy with, looks like this.
Register eventhandlers for user action, which lead to ajax requests.
For each request:
Determine which container is the target for the new content
Validate the ajax response
Pass the result to the appropiate rendering function if everything is as expected
Here is an example
function setGamedayScoringChangeHandlers() {
$("#community").delegate("div.community div.nav", "click", function() {
var orderId = $(this).html();
var communityId = $(this).closest('.communityView ').dashId();
requestGamedayScoringByOrderId(communityId, orderId);
});
}
function requestGamedayScoringByOrderId(communityId, orderId) {
var $targetContainer = $('#community-' + communityId + '-gameday');
$.ajax({
url: '?api=league&func=getGamedayScoringByCommunityIdAndOrderId',
data: {
communityId : communityId,
orderId : orderId
},
success: function(result) {
// custom indicator, that sth. didn't work as supposed
if (result.success === false) {
// a php error couldn't be handled as expected
if (result.error === 'phpRuntimeError') {
// ..
}
// ..
}
else {
renderGamedayScoring(result, $targetContainer);
}
}
});
}
Question
How can this and especially the redundant error checking be simplified? Could Reflection, in a sense of: "Is the response valid? And what does the error message say or data look like?" be a reasonable structure do deal with this? Additionally: Is the "coupling" of the actual ajax request and determing the $targetContainer a "normal" procedure?
Many thanks,
Robson
Yes I think register ajax handler trought one pipe is a good way, because it is more easy to control, you will have less redundant code and less boarding effects. If I look at your code comments it seems the response is not as you expect. I use to do like this for controling a group of ajax request talking with server script. I build one request object like :
// myscript.js
var rqPHP = {
url:'php/dispatcher.php', type:'POST', dataType:'json',
success:function(json, status, jXHR){
//console.log('rqPHP.succes : ', json);
if(!json) return console.warn('[rqPHP.success] json is null');
if(!json.cmd) return console.warn('[rqPHP.success] json.cmd is null');
if(!json.res) return console.warn('[rqPHP.success] json.res is null');
if(json.err && json.err.length){ console.warn('[rqPHP.success errors cmd:'+json.cmd+'] '+json.err);}
// so if no errors, dispatch actions based on original command asked
switch(json.cmd){
case 'loadfile' :
// do whatever with response
break;
case 'savefile' :
// do whatever with response
break;
}
},
error:function(jXHR, status, err){
console.warn('[rqPHP.error] ', status,',',err,',',jXHR.responseText);
}
};
then when use this object trought all my group of different actions and I precise wich action and arguments I pass. I use to ask for a json data so I am able to receive an easy parsing response, so I am able to return the original command asked, and some details on errors that may occured for example, and when I need to fire the request :
// myscript.js
rqPHP.data = {'cmd':'loadfile', 'filename':'file.dat', 'arg2':'other argument'};
$.ajax(rqPHP);
Then an example of one server script that will respond :
// dispatcher.php
$pv = $_POST;
$res = '';
$err = array();
// you check the command asked for :
switch(strtolower($pv['cmd'])){
case 'savefile' :
// do whatever
break;
case 'loadfile' :
// do whatever
if(any error){
$err[] = $loadError;// push error with whatever details you'll retrieve in javascript
}else{
$res = ',"res":"'.$dataLoaded.'"';// format json response so you'll check the var exist
}
break;
}
$jsonRes = '{"cmd":"'.$pv['cmd'].'"'.$res.',"err":"'.implode('|', $err).'"}';// json result
print $jsonRes;
They may be some errors, it is just for the principe, I hope that will help, just some last advices :
you should better use the requestObject.data to pass any arguments instead of setting the url like you did, this is much more easy because jQuery does the properly encoding work
you may use POST so the url stay clean, post vars are 'hidden'
in your case, because you may want to centralize server actions with ONE server script, you should use 'json' as dataType because it is much easier to retrieve details from the response, such errors. You have to distinct the ajax error that is trigger when the url doesn't exist, or access denied, well when the server replies it just can't respond to this request, and distinct the properly response of your server script, I mean the script responds well but it may occur an command error, for example for a 'loadfile' command, the argument fileUrl may be wrong or unreadable, so the action is done but the response will be not valid for you...
If you plan to fire many loads for differents parts (I mean you may don't wait response for an ajax before loading a new one), it should be better to set main success and errors functions for keeping centralization and then build one new request object each time you make a load
function rqSuccess(json, status, jXHR){
// put same checking code as before, then you can also retrieve some particular variables
// here, 'this' should correspond to the request object used for the $.ajax so :
console.log('myTarget is : ', this.myTarget, ' , myVariable is : ', this.myVariable);
}
function rqError(jXHR, status, err){
// put same checking code
}
// then each time you want make one or many independant calls, build a new request object
var myRq = {url:'dispatcher.php',type:'POST',dataType:'json',
success:rqSuccess,
error:rqError,
myTarget:$('#myblock'),// any variable you want to retrieve in response functions
myVariable:'Hello !',// after all it is an object, you can store anything you may need, just be carefull of reserved variables of the ajax object (see jQuery $.ajax doc)
// the data object is sanitized and sended to your server script, so put only variables it will need
data : {'cmd':'loadfile',...}
}
$.ajax(myRq);
// you may load an other independant one without waiting for the response of the first
var myRq2 = {...myTarget:$('#anotherblock'), data:{'cmd':'anotheraction'}...}
$.ajax(myRq2);
As a first step, you should change the error handling on the serverside to produce a non-OK/200 response for error cases, e.g. throw a 500. Then have that handled as an actual error on the clientside, along with other errors, instead of putting it through the success-callback.
That way you can use jQuery's abstractions for global error handling: http://api.jquery.com/ajaxError
I've build a livesearch with the jQuery.ajax() method. On every keyup events it receives new result data from the server.
The problem is, when I'm typing very fast, e.g. "foobar" and the GET request of "fooba" requires more time than the "foobar" request, the results of "fooba" are shown.
To handle this with the timeout parameter is impossible, I think.
Has anyone an idea how to solve this?
You can store and .abort() the last request when starting a new one, like this:
var curSearch;
$("#myInput").keyup(function() {
if(curSearch) curSearch.abort(); //cancel previous search
curSearch = $.ajax({ ...ajax options... }); //start a new one, save a reference
});
The $.ajax() method returns the XmlHttpRequest object, so just hang onto it, and when you start the next search, abort the previous one.
Assign a unique, incrementing ID to each request, and only show them in incrementing order. Something like this:
var counter = 0, lastCounter = 0;
function doAjax() {
++counter;
jQuery.ajax(url, function (result) {
if (counter < lastCounter)
return;
lastCounter = counter;
processResult(result);
});
}
You should only start the search when the user hasn't typed anything for a while (500ms or so). This would prevent the problem you're having.
An excellent jQuery plugin which does just that is delayedObserver:
http://code.google.com/p/jquery-utils/wiki/DelayedObserver
Make it so each cancels the last. That might be too much cancellation, but when typing slows, it will trigger.
That seems like an intense amount of traffic to send an ajax request for every KeyUp event. You should wait for the user to stop typing - presumably that they are done, for at least a few 100 milliseconds.
What I would do is this:
var ajaxTimeout;
function doAjax() {
//Your actual ajax request code
}
function keyUpHandler() {
if (ajaxTimeout !== undefined)
clearTimeout(ajaxTimeout);
ajaxTimeout = setTimeout(doAjax, 200);
}
You may have to play with the actual timeout time, but this way works very well and does not require any other plugins.
Edit:
If you need to pass in parameters, create an inline function (closure).
...
var fun = function() { doAjax(params...) };
ajaxTimeout = setTimeout(fun, 200);
You will want some kind of an ajax queue such as:
http://plugins.jquery.com/project/ajaxqueue
or http://www.protofunc.com/scripts/jquery/ajaxManager/
EDIT:Another option, study the Autocomplete plug-in code and emulate that.(there are several Autocomplete as well as the one in jquery UI
OR just implement the Autocomplete if that serves your needs