How to add a pause between 2 requests in POSTMAN - http

I have a collection of requests in POSTMAN. I wanted to add a pause between 2 requests but I couldn't find a way to do so from reading their docs. Any idea?
UPDATE I only wanted to put a pause after one request instead of after every request in the collection.

In case someone is still looking for this - You can add delay after/before 1 of many test in a collection you can use:
setTimeout(function(){}, [number]);
where 'number' is the milliseconds. If it's added at 'Tests' it will be executed after request is send. If it's added at Pre-request Scripts it will be executed before request is send.

Using javascript's busy wait is a good hack but it makes your CPU hot and the app unresponsive. I figured out this solution using postman-echo.
Assuming you want to add a long delay between Request_A and Request_B.
First, in Request_A's test script set up an env var to mark the start.
environment.delayTimerStart = new Date();
Then, create a GET request in the creation (here called 'Delay 10s'). It makes a GET on https://postman-echo.com/delay/10 (It returns after 10s)
In its test script, add
var curDate = new Date();
if (curDate - environment.delayTimerStart < delay_time_in_sec*1000) {
postman.setNextRequest('Delay 10s');
} else {
postman.setNextRequest("Request_B");
}
In this way you can add a delay of any length.
Note: 10 sec is the maxium value that postman-echo accepts. If you just need a short delay, simply GET https://postman-echo.com/delay/[1~10].

Try something like this-
if(jsonBody.responseCode=="SUCCESS"){
setTimeout(function(){
console.log("Sleeping for 3 seconds before next request.");
}, 3000);
postman.setNextRequest("nextAPI");
}

I know two possible ways to do this
Method I
Run your request as a collection. (https://www.getpostman.com/docs/collections)
Use Newman (Postman's collection runner from command line) to run your collection with --delay flag. The delay input value is in milliseconds.
Method II
This is a nice hack which I found here https://github.com/postmanlabs/postman-app-support/issues/1038. You can add a delay function to your test script in Postman.

Just simple example, I'm sure you will be understand.
setTimeout(() => {}, 15000);
15000 it's a value in miliseconds

looking at the current documentation if you are using Postman Runner
Delay
This is the interval (in ms) between each request in your collection run.
https://www.getpostman.com/docs/postman/collection_runs/starting_a_collection_run
and if you are using newman
--delay-request [number] Specify a delay (in ms) between requests [number]
https://www.getpostman.com/docs/postman/collection_runs/command_line_integration_with_newman

If you have the standalone Postman App (supports ES7) and you are intending to test only on Postman, not on newman(which doesn't support ES7), then you can have something like this in the Pre-Request script of the Request you want to delay:
function foo() {
return (new Promise((resolve, reject) => {
setTimeout(() => {
resolve("done!"); // passing argument is optional, can just use resolve()
}, 10000) // specify the delay time in ms here..
}))
}
async function waitForMe() {
await foo().then((val) => {
console.log(val); // not required, you can just do an await without then
})
}
waitForMe();

I prefer to use an online service Postman Echo's delay endpoint (docs are here). Simply create a request that uses this service and call it between the two other requests you wish to add a delay between.
If you want to check the status of something before continuing, you can use postman.setNextRequest() in the Tests of a request to loop until something has been completed. Simply do the following:
1) Create a collection structured as:
Delay For 10 Seconds
Status Check
Continue Processing
2) In the Status Check request Tests:
if(responseBody.has("Success")) //or any other success condition
{
postman.setNextRequest('Continue Processing');
tests["Success found"] = true;
}
else
{
postman.setNextRequest('Delay For 10 Seconds');
tests["No success found"] = true;
}

You can use JavaScript setTimeout method. This will make sure that your method will be executed after given delay.
setTimeout(checkStatusCode, 500);
function checkStatusCode() {
pm.sendRequest('https://postman-echo.com/get', function (err, res) {
tests['status code should be 200']= res.code ===200;
});
}

Related

Asynchronous execution of a function App Script

I've been digging around, and I'm not able to find references or documentation on how I can use Asynchronous Functions in Google App Script, I found that people mention It's possible, but not mention how...
Could someone point me in the right direction or provide me with an example?
Promises, Callbacks, or something, that can help me with this.
I have this function lets call it foo that takes a while to execute (long enough that It could time out an HTTP call).
What I'm trying to do Is to refactor it, in a way that it works like this:
function doPost(e) {
// parsing and getting values from e
var returnable = foo(par1, par2, par3);
return ContentService
.createTextOutput(JSON.stringify(returnable))
.setMimeType(ContentService.MimeType.JSON);
}
function foo(par1, par2, par3) {
var returnable = something(par1, par2, par3); // get the value I need to return;
// continue in an Async way, or schedule execution for something else
// and allow the function to continue its flow
/* async bar(); */
return returnable;
}
Now I want to realize that bit in foo because It takes to long and I don't want to risk for a time out, also the logic that occurs there it's totally client Independent, so It doesn't matter, I just need the return value, that I'll be getting before.
Also, I think It's worth mentioning that this is deployed in Google Drive as a web app.
It's been long since this, but adding some context, at that moment I wanted to scheduled several things to happen on Google Drive, and It was timing out the execution, so I was looking for a way to safely schedule a job.
You want to execute functions by the asynchronous processing using Google Apps Script.
You want to run the functions with the asynchronous processing using time trigger.
If my understanding is correct, unfortunately, there are no methods and the official document for directly achieving it. But as a workaround, that can be achieved by using both Google Apps Script API and the fetchAll method which can work by asynchronous processing.
The flow of this workaround is as follows.
Deploy API executable, enable Google Apps Script API.
Using fetchAll, request the endpoint of Google Apps Script API for running function.
When several functions are requested once, those work with the asynchronous processing by fetchAll.
Note:
I think that Web Apps can be also used instead of Google Apps Script API.
In order to simply use this workaround, I have created a GAS library. I think that you can also use it.
In this workaround, you can also run the functions with the asynchronous processing using time trigger.
References:
fetchAll
Deploy the script as an API executable
scripts.run of Google Apps Script API
Benchmark: fetchAll method in UrlFetch service for Google Apps Script
GAS library for running the asynchronous processing
If I misunderstand your question, I'm sorry.
There is another way to accomplish this.
You can use time-based one-off triggers to run functions asynchronously, they take a bit of time to queue up (30-60 seconds) but it is ideal for slow-running tasks that you want to remove from the main execution of your script.
// Creates a trigger that will run a second later
ScriptApp.newTrigger("myFunction")
.timeBased()
.after(1)
.create();
There is handy script that I put together called Async.gs that will help remove the boilerplate out of this technique. You can even use it to pass arguments via the CacheService.
Here is the link:
https://gist.github.com/sdesalas/2972f8647897d5481fd8e01f03122805
// Define async function
function runSlowTask(user_id, is_active) {
console.log('runSlowTask()', { user_id: user_id, is_active: is_active });
Utilities.sleep(5000);
console.log('runSlowTask() - FINISHED!')
}
// Run function asynchronously
Async.call('runSlowTask');
// Run function asynchronously with one argument
Async.call('runSlowTask', 51291);
// Run function asynchronously with multiple argument
Async.call('runSlowTask', 51291, true);
// Run function asynchronously with an array of arguments
Async.apply('runSlowTask', [51291, true]);
// Run function in library asynchronously with one argument
Async.call('MyLibrary.runSlowTask', 51291);
// Run function in library asynchronously with an array of arguments
Async.apply('MyLibrary.runSlowTask', [51291, true]);
With the new V8 runtime, it is now possible to write async functions and use promises in your app script.
Even triggers can be declared async! For example (typescript):
async function onOpen(e: GoogleAppsScript.Events.SheetsOnOpen) {
console.log("I am inside a promise");
// do your await stuff here or make more async calls
}
To start using the new runtime, just follow this guide. In short, it all boils down to adding the following line to your appsscript.json file:
{
...
"runtimeVersion": "V8"
}
Based on Tanaike's answer, I created another version of it. My goals were:
Easy to maintain
Easy to call (simple call convention)
tasks.gs
class TasksNamespace {
constructor() {
this.webAppDevUrl = 'https://script.google.com/macros/s/<your web app's dev id>/dev';
this.accessToken = ScriptApp.getOAuthToken();
}
// send all requests
all(requests) {
return requests
.map(r => ({
muteHttpExceptions: true,
url: this.webAppDevUrl,
method: 'POST',
contentType: 'application/json',
payload: {
functionName: r.first(),
arguments: r.removeFirst()
}.toJson(),
headers: {
Authorization: 'Bearer ' + this.accessToken
}
}), this)
.fetchAll()
.map(r => r.getContentText().toObject())
}
// send all responses
process(request) {
return ContentService
.createTextOutput(
request
.postData
.contents
.toObject()
.using(This => ({
...This,
result: (() => {
try {
return eval(This.functionName).apply(eval(This.functionName.splitOffLast()), This.arguments) // this could cause an error
}
catch(error) {
return error;
}
})()
}))
.toJson()
)
.setMimeType(ContentService.MimeType.JSON)
}
}
helpers.gs
// array prototype
Array.prototype.fetchAll = function() {
return UrlFetchApp.fetchAll(this);
}
Array.prototype.first = function() {
return this[0];
}
Array.prototype.removeFirst = function() {
this.shift();
return this;
}
Array.prototype.removeLast = function() {
this.pop();
return this;
}
// string prototype
String.prototype.blankToUndefined = function(search) {
return this.isBlank() ? undefined : this;
};
String.prototype.isBlank = function() {
return this.trim().length == 0;
}
String.prototype.splitOffLast = function(delimiter = '.') {
return this.split(delimiter).removeLast().join(delimiter).blankToUndefined();
}
// To Object - if string is Json
String.prototype.toObject = function() {
if(this.isBlank())
return {};
return JSON.parse(this, App.Strings.parseDate);
}
// object prototype
Object.prototype.toJson = function() {
return JSON.stringify(this);
}
Object.prototype.using = function(func) {
return func.call(this, this);
}
http.handler.gs
function doPost(request) {
return new TasksNamespace.process(request);
}
calling convention
Just make arrays with the full function name and the rest are the function's arguments. It will return when everything is done, so it's like Promise.all()
var a = new TasksNamespace.all([
["App.Data.Firebase.Properties.getById",'T006DB4'],
["App.Data.External.CISC.Properties.getById",'T00A21F', true, 12],
["App.Maps.geoCode",'T022D62', false]
])
return preview
[ { functionName: 'App.Data.Firebase.Properties.getById',
arguments: [ 'T006DB4' ],
result:
{ Id: '',
Listings: [Object],
Pages: [Object],
TempId: 'T006DB4',
Workflow: [Object] } },
...
]
Notes
it can handle any static method, any method off a root object's tree, or any root (global) function.
it can handle 0 or more (any number) of arguments of any kind
it handles errors by returning the error from any post
// First create a trigger which will run after some time
ScriptApp.newTrigger("createAsyncJob").timeBased().after(6000).create();
/* The trigger will execute and first delete trigger itself using deleteTrigger method and trigger unique id. (Reason: There are limits on trigger which you can create therefore it safe bet to delete it.)
Then it will call the function which you want to execute.
*/
function createAsyncJob(e) {
deleteTrigger(e.triggerUid);
createJobsTrigger();
}
/* This function will get all trigger from project and search the specific trigger UID and delete it.
*/
function deleteTrigger(triggerUid) {
let triggers = ScriptApp.getProjectTriggers();
triggers.forEach(trigger => {
if (trigger.getUniqueId() == triggerUid) {
ScriptApp.deleteTrigger(trigger);
}
});
}
While this isn't quite an answer to your question, this could lead to an answer if implemented.
I have submitted a feature request to Google to modify the implementation of doGet() and doPost() to instead accept a completion block in the functions' parameters that we would call with our response object, allowing additional slow-running logic to be executed after the response has been "returned".
If you'd like this functionality, please star the issue here: https://issuetracker.google.com/issues/231411987?pli=1

Meteor How to block a method call before the first one is finished?

I have the following scenario:
Client side has a button clicking it will execute Meteor.call method on the server-side which will call API and fetch products, During this time I wan't to disable this button + block this method from executing again basically nothing stops you from clicking the button 100x times and server will keep on executing same method again and again.
Few ideas I had in my mind: Use sessions to disable button (Problem: can still using the console Meteor.call and abuse it)
I also looked at Meteor.apply in the docs with wait:true didn't seems to stop from method execution. I honestly not sure how this kind of thing is handled with no hacks.
Client-side:
'click .button-products': function(e){
Meteor.call('getActiveProducts', function(error, results){
if (error)
return Alerts.add(error.reason, 'danger', {autoHide: 5000});
if (results.success)
return Alerts.add('Finished Importing Products Successfully', 'success', {autoHide: 5000});
})
}
Server-side
Meteor.methods({
getActiveProducts: function(){
var user = Meteor.user();
var api = api.forUser(user);
importProducts = function(items){
nextPage = items.pagination.next_page;
items.results.forEach(function(product){
var sameproduct = apiProducts.findOne({listing_id: product.listing_id});
if (sameproduct) {
return;
}
var productExtend = _.extend(product, {userId: Meteor.userId()});
apiProducts.insert(productExtend);
});
};
var products = api.ProductsActive('GET', {includes: 'Images', limit: 1});
importProducts(products);
while (nextPage !== null) {
products = api.ProductsActive('GET', {includes: 'Images', page: nextPage, limit: 1});
importProducts(products);
}
return {success: true};
}
});
From the Meteor docs:
On the server, methods from a given client run one at a time. The N+1th invocation from a client won't start until the Nth invocation returns. However, you can change this by calling this.unblock. This will allow the N+1th invocation to start running in a new fiber.
What this means is that subsequent calls to the method won't actually know that they were made while the first call was still running, because the first call will have already finished running. But you could do something like this:
Meteor.methods({
getActiveProducts: function() {
var currentUser = Meteor.users.findOne(this.userId);
if (currentUser && !currentUser.gettingProducts) {
Meteor.users.update(this.userId, {$set: {gettingProducts: true}});
// let the other calls run, but now they won't get past the if block
this.unblock();
// do your actual method stuff here
Meteor.users.update(this.userId, {$set: {gettingProducts: false}});
}
}
});
Now subsequent calls may run while the first is still running, but they won't run anything inside the if block. Theoretically, if the user sends enough calls, the first call could finish before all of the others have started. But this should at least significantly limit the number of etsy calls that can be initiated by a user. You could adapt this technique to be more robust, such as storing the last time a successful call was initiated and making sure X seconds have passed, or storing the number of times the method has been called in the last hour and limiting that number, etc.
A package I wrote a while back might come in handy for you. Essentially it exposes the Session api on the server side (hence the name), meaning you can do something like ServerSession.set('doingSomethingImportant', true) within the call, and then check this session's value in subsequent calls. The session can only be set on the server, and expires upon connection close (so they could spam calls, but only as fast as they can refresh the page).
In the event of error, you can just reset the session. There shouldn't be any issues related to unexpected errors either because the session will just expire upon connection close. Let me know what you think :)

How to use wrapAsync in Meteor

I am having trouble figuring out how to use wrapAsync properly using Meteor. I am currently working with node-apac and the Amazon Product Advertising API.
If am trying to run the following code, how do I run it asynchronously:
opHelper.execute('ItemSearch', {
'SearchIndex': 'Books',
'Keywords': 'harry potter',
'ResponseGroup': 'ItemAttributes, Offers'
}, function(err, results) {
console.log(results);
});
I have tried to watch several videos, but am having trouble
Meteor.wrapAsync takes an asynchronous method like opHelper.execute and makes it synchronous. It can do this so long as the last param taken by the method returns a callback where the first param is the error and second the result. This is just like your method!
You make a new method that is synchronous:
var opExecuteSynchronous = Meteor.wrapAsync(opHelper.Execute, opHelper);
The first param opHelper.Execute is the method you want to make asynchronous, and the second param is the context of the method (opHelper).
You can use this synchronously now:
var results = opExecuteSynchronous('ItemSearch', {
'SearchIndex': 'Books',
'Keywords': 'harry potter',
'ResponseGroup': 'ItemAttributes, Offers'
})
This will throw an error if err is called instead of results in the callback.

Meteor external API calls limit the calls or Sleep?

I wasn't able to find any information on how you can sleep for 1 second or limit the amount of calls per some time in meteor or javascript seems like there is no simple sleep function? Here is my code how should I go about limiting or sleeping the right way? (Or should I just hack my way on doing this?) all tips are welcome!
call = function(method, endpoint, params) {
try {
params = _.extend({}, params || {});
var data = HTTP.call(method, endpoint, {data: params});
return data;
} catch (err) {
throw new Error("Failed to fetch call " + err.message);
}
};
OK, So supposedly there is undocumented server only sleep function in Meteor Meteor._sleepForMs(5000); simpler than using setTimeout function. I didn't choose what I will pick but this might help somebody else as well.
Good way to make pauses or intervals in Meteor is to use Timers, such as setTimeout()
or setInterval()

Get callback info back to original calling function

Let's say you have a Javascript function that calls a web service method. So that webservice completes and calls a callback function, which has the result.
How do I get that result back into the original function that called the web service method? Essentially, I'm trying to "synchronize" an asynchronous call.
Update:
This is what I'm trying to do. I'm validating based on the return value of a web service.
$.validator.addMethod("zzz",
function(value, element) {
// Call web service function using ASP.NET Ajax.
// Get callback value to determine validity.
return this.optional(element) || ***return t/f based on validity***;
},
function(value, element) { return msg; }
);
so I guess I could do this instead:
$.validator.addMethod("zzz",
function(value, element) {
$.ajax({
async: false
url: **** web service url ****
success: set t/f to validity var
});
return this.optional(element) || ***return t/f based on validity var***;
},
function(value, element) { return msg; }
);
Since you're using jQuery, you can use async:false in your ajax command, like this:
$.ajax({
//options..
async: false
});
//this code will run after the request returns
Note though, this blocks the UI (locks up the browser), it's better to continue the work that depends on the result in the success callback, like this:
$.ajax({
//options..
success: function(data) {
doSomethingWithResult(data);
}
});
Essentially, you can't, but you can break up that function into "before" and "after" parts, like so:
function foo(a) {
var b, c;
// == The "before" part:
b = /* ... */;
// == Call the service:
callWebService(a, b, callback);
// == The "after" part is contained within the callback:
function callback(d) {
// Do something with a, b, c, and d
}
}
But it's important to note that foo will return before callback is called. There's no way to prevent that with an asynchronous call, so if you're looking to have the function return something, you'll have to refactor (or use a synchronous call, but that's a very bad idea). The refactoring would involve whatever's calling foo to provide a callback and expect the result to be provided that way rather than as a return value.
Well what you're trying to accomplish is simulating a sleep command, so your script "waits" for your ajax request? But that doesn't really makes sense. That's why you have to callback in the first place, to continue with the flow once the request has returned a reply, since you cannot predict its response time.
Not to be trite, but you can't create synchronousness from asynchronousness, only the other way around. You need to design your code to allow for this, which generally means callbacks all the way through your call chain.
There is one idiosyncratic exception, which is that you can specify 'false' on the raw XMLHttpRequest's 'open' method's async parameter, which will cause the send method to block until it's done. But this is likely not compatible with some frameworks and is pretty inflexible. Most JS stuff is async.
You should not do that. Just carry on with your processing from the point of the callback.
You risk hanging the browser completely if the call does not return.
If you control the server side then you could write some code on the js side to aggregate calls and then write something on the server side to unpack and do multiple calls from each nested call in the aggregate. When the responses come back then aggregate those and send them back. This will save on performance since large calls are cheaper than many small calls.
We did that on a project I worked on and it worked very nicely. It also consolidates logic on the js side to not be spread all over due to all the async callbacks.
The only way I can think of is like
function b(){
var a = null;
$.get("abc.json", {
success: function(data){
a = data;
}
});
while(a == null){}
alert(a);
}
b();
But generally this isn't good and may cause the browser to complain a script is taking too long to finish.

Resources