Can't able to call the rest api's asynchoronously - alamofire

I am new to ios threads. While calling the api in the particular screen its not giving the response until 60 seconds, In between time am calling other api's from same screens or other screens its kept loading. After 60 seconds, it will show the response.
We need to call the asynchronous api's using Alamofire. but its not working
private let alamofireManager : Session
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 300 // seconds
configuration.timeoutIntervalForResource = 500
alamofireManager = Session.init(configuration: configuration, serverTrustManager: .none)
alamofireManager.request("sample_api",method: .post,parameters: parameters,encoding: URLEncoding.default,headers: nil).responseJSON { (response) in}

First, when getting started it's not necessary to customize anything. Especially when the values you're customizing aren't much different from the defaults.
Second, Alamofire 5.6 now ships with Swift async / await APIs, so I suggest you use those when getting started. You can investigate your network calls without tying them to specific screens until you understand the calls, how they work, and when they should be called.
Third, a 60 second delay sounds like a timeout, as 60 seconds is the default timeout wait. Is that expected? Make sure you have proper access to your server. You should also print your response so you can see what's happening and whether you got data back or an error.
Fourth, use a Decodable type to encapsulate your expected response, it makes interacting with various APIs much simpler. Do not use Alamofire's responseJSON, it's now deprecated.
So you can start your experiment by using Alamofire's default APIs.
let response1 = await AF.request("url1").serializingDecodable(Response1.self)
debugPrint(response1)
let response2 = await AF.request("url2").serializingDecodable(Response2.self)
debugPrint(response2)

Related

Expressjs send content after listen

I want to make a route in express js to send some content after 1000 ms.
Note: I cant use res.sendFile, it has to be a plain route.
This is the code for the route:
app.get('/r', (req,res)=>{
res.send("a")
setTimeout(()=>{
res.send("fter")
}, 1000)
}
app.listen(8080)
But I get the error: ERR_HTTP_HEADERS_SENT, I assume because the page has already been loaded.
I need my node program to send it after it has already been loaded, so I cant like send a html,js,css script to do it. Is it possible? I cant seem to find how.
Well, if that is not possible, what I am really trying to do is after the page has loaded, execute js or send a message that the page can receive from the node program, like if there was res.execute_js('postMessage(1)')
EDIT based on your edit: So as I understand you want a way to send different values from a node app endpoint without using socketio. I've managed to replicate a similar experimental behavior using readable streams. Starting off, instead of returning response to the request with res.send() you should be using res.write() In my case I did something like this:
app.post('/api', (req, res) => {
res.write("First");
setTimeout(() => {
res.write("Second");
res.end();
}, 1000);
});
This will write to a stream "First" then after 1000ms it'll write another "Second" chunk then end the stream, thus completing the POST request.
Now in the client, you'll make the fetch response callback async, get the ReadableStream from the request like so
const reader = response.body.getReader();
now we should be reading this stream, we'll first initialize an array to collect all what we're reading,
const output = [];
now to actually read the stream,
let finished, current;
while (!finished) {
({ current, finished} = await reader.read());
if (finished) break;
output.push(current);
}
if you read current in the loop, it'll contain each value we passed from res.write() and it should read twice, "First" and after 1000ms "Second".
EDIT: This is very experimental however, and I wouldn't recommend this in a production codebase. I'd suggest trying out socketio or a publish/subscribe mechanism instead.
Old answer: You're already sending "a" back, you should remove the first res.send() invocation at the top of the callback.
So, this is for all the people wondering. No you cannot do this with pure express (there is a workaround, so keep reading).
The reason you cant do this is because, when the user requests to the url, it sends them a response, and the browser renders it. You cant then tell it to change the response, as the browser has already received a response. Even if you send multiple, like with res.write, rather then res.send, the browser will just wait until it receives all the data.
Here are two workarounds:
    1. Use socket.io, cscnode, or another library to have events for updating text,
    2. Send hardcoded html, that updates text (1 was probably better)
That is all I think you can do.
More clarification on the socketio one is basically have an event for changing text that you can fire from node, and the browser will understand, and change the text.

Refresh a function every 3 seconds in react native

I was wondering if it is okay to set the time interval to trigger a function every 3 seconds. Let's say I have 5 different screens in my application and all 5 screens have the time interval set to 3 seconds and will keep on calling a function to auto refresh the screen.
My concern is, will it cause a heavy traffic to the server if there are multiple users using the app at the same time and the server will keep on receiving the request from the app?
Sample code :
componentDidMount(){
this.interval = setInterval(() => {
this.loadCase()
}, 3000);
}
componentWillUnmount(){
clearInterval(this.interval);
}
loadCase(){
CaseController.loadCase().then(data=>{
if(data.status == true){
this.setState({ case: data.case })
}
})
}
If you have an API endpoint that you need to poll every 3 seconds and you're looking to avoid redundant calls from the app, try using setInterval in your App.js, or wherever the root of your app is, and dump the result into Redux/whatever state management solution you're using so that you can access it elsewhere.
To answer your question regarding "heavy traffic," yeah, that is inevitably going to be a lot of API calls that your server will need to handle. If it's going to cause issues with the current setup of your API server, I would look closely at your app and see if there's a way you can reduce the effects that large numbers of users will have, whether that's some sort of caching, or increasing the amount of time between API calls, or entirely reconsidering this approach.

How to unit test a method that waits for a response to an asynchronous message

I have a WCF service that sends a message to a remote device via an asynchronous messaging protocol (MQTT), then it has to wait for a response from the device in order to simulate a synchronous operation.
I'm doing this by creating a TaskCompletionSource (and a CancellationTokenSource to handle a timeout), storing it in a ConcurrentDictionary, then returning the TCS.Task.Result once it is set. Meanwhile, when the response comes in, a different method handles the response by looking up the TCS in the dictionary and setting its Result accordingly.
This all seems to work in practice, but I'm running into issues when trying to unit test this method. I'm trying to set up an asynchronous task that waits for the SendMessage method to generate the TCS and add it to the dictionary, then simulates a response by pulling it out of the dictionary and setting the result before the timeout elapses.
For the purposes of the unit test, I'm using a timeout period of 500 ms. I've tried this:
Task.Run(() =>
{
Thread.Sleep(450);
ctsDictionary.Values.Single().SetResult(theResponse);
});
MessageResponse response = service.SendMessage(...);
I've also tried this:
MessageResponse response = null;
Parallel.Invoke(
async () =>
{
await Task.Delay(250);
ctsDictionary.Values.Single().SetResult(theResponse);
},
() =>
{
response = service.SendMessage(...)
}
);
Both of these strategies work fine when running just this one unit test or even when running all tests in this Unit Test class.
The problem comes when running all unit tests for the solution (2307 tests in total across a couple dozen UnitTest projects). This test consistently fails with the SendMessage method timing out before the response gets set by the asynchronous task, when part of a "Run All Tests" operation. Presumably this is because the scheduling of the tasks is thrown off by all the other unit tests that are being run in parallel, and the timing doesn't end up working out. I've tried playing around with the delay on the task as well as increasing the timeout period considerably, but I still can't get it to consistently pass when all tests are run.
So how can I fix this? Is there some way I can ensure that the SendMessage call and the task that sets the response are scheduled to run at the exact same time? Or is there some other strategy I can use to ensure the timing works out?
then it has to wait for a response from the device in order to simulate a synchronous operation.
That's hokey, man. Just have to say it - keep it async. Not only would it be more natural, it would be easier to unit test!
You can minimize the time SendMessage is waiting by first queueing up the SendMessage and then fast-polling for the request to hit the dictionary. That's as tight as you can get it without changing SendMessage (e.g., making it async):
// Start SendMessage
var sendTask = Task.Run(() => service.SendMessage(...));
// SendMessage may not actually be running yet, so we busy-wait for it.
while (ctsDictionary.Values.Count == 0) ;
// Let SendMessage know it can return.
ctsDictionary.Values.Single().SetResult(theResponse);
// Retrieve the result.
var result = await sendTask;
If you still have problems getting in before the timeout, you'll just have to throttle your unit tests (e.g., SemaphoreSlim).
Again, this would be much easier if SendMessageAsync existed with the semantics that it synchronously adds to the dictionary before it awaits:
// Start SendMessage
var sendTask = service.SendMessageAsync(...);
// Let SendMessage know it can return.
ctsDictionary.Values.Single().SetResult(theResponse);
// Retrieve the result.
var result = await sendTask;
No busy-waiting, no delays, no extra threads. Much cleaner.

Flux without data caching?

Almost all examples of flux involve data cache on the client side however I don't think I would be able to do this for a lot of my application.
In the system I am thinking about using React/Flux, a single user can have 100's of thousands of the main piece of data we store (and 1 record probably has at least 75 data properties). Caching this much data on the client side seems like a bad idea and probably makes things more complex.
If I were not using Flux, I would just have a ORM like system that can talk to a REST API in which case a request like userRepository.getById(123) would always hit the API regardless if I requested that data in the last page. My idea is to just have the store have these methods.
Does Flux consider it bad that if I were to make request for data, that it always hit the API and never pulls data from a local cache instance? Can I use Flux in a way were a majority of the data retrieval requests are always going to hit an API?
The closest you can sanely get to no caching is to reset any store state to null or [] when an action requesting new data comes in. If you do this you must emit a change event, or else you invite race conditions.
As an alternative to flux, you can simply use promises and a simple mixin with an api to modify state. For example, with bluebird:
var promiseStateMixin = {
thenSetState: function(updates, initialUpdates){
// promisify setState
var setState = this.setState.bind(this);
var setStateP = function(changes){
return new Promise(function(resolve){
setState(changes, resolve);
});
};
// if we have initial updates, apply them and ensure the state change happens
return Promise.resolve(initialUpdates ? setStateP(initialUpdates) : null)
// wait for our main updates to resolve
.then(Promise.params(updates))
// apply our unwrapped updates
.then(function(updates){
return setStateP(updates);
}).bind(this);
}
};
And in your components:
handleRefreshClick: function(){
this.thenSetState(
// users is Promise<User[]>
{users: Api.Users.getAll(), loading: false},
// we can't do our own setState due to unlikely race conditions
// instead we supply our own here, but don't worry, the
// getAll request is already running
// this argument is optional
{users: [], loading: true}
).catch(function(error){
// the rejection reason for our getUsers promise
// `this` is our component instance here
error.users
});
}
Of course this doesn't prevent you from using flux when/where it makes sense in your application. For example, react-router is used in many many react projects, and it uses flux internally. React and related libraries/patters are designed to only help where desired, and never control how you write each component.
I think the biggest advantage of using Flux in this situation is that the rest of your app doesn't have to care that data is never cached, or that you're using a specific ORM system. As far as your components are concerned, data lives in stores, and data can be changed via actions. Your actions or stores can choose to always go to the API for data or cache some parts locally, but you still win by encapsulating this magic.

Caching best practice for mobile hybrid/bridge app development

I really need to limit any unnecessary network traffic and server trips. Solution: common sense caching. (I am not going to cache everything under the sun).
However, after reading through the Caching Files documentation and implementing a couple of quick examples, when is the best time to cache an ajax json result? Sure I can do the usual cache/no cache check each time my view is displayed. But is there a way to perform an asynchronous load during initial application startup to prefetch remote data that I know the user is going to need? Is using the connectionStateChanged event the only way (or closest way)? Is there a way to "hook" into the splash screen (yes, I know Apple wants the splash screen for mostly transition)? window.onload?
So if I understand you correctly, you're looking for a way to asynchronously fetch remote resources once for each time the app starts up, and cache those data away?
Our request module is asynchronous by nature, so you could simply drop in a forge.request.ajax to start fetching an Ajax response, then store it away in the preferences module.
Although it's probably identical in practice, you could even wrap it in a setTimeout to make it even more asynchronous:
setTimeout(function ()
forge.request.ajax({
url: 'http://example.com/method.json',
success: function (data) {
forge.prefs.set("method.json-cache", data);
}
});
}, 10);