Source on GitHub
Definition: shared/definitions/async-functions.json
shared/client/async-functions.js · sjs:async-functions.client
View on GitHub
import { registerFunction } from "survey-core";
// Validation: does a customer with this email already exist?
registerFunction({
name: "emailExists",
isAsync: true,
func: async ([email]) => {
if (!email) return false;
const res = await fetch(`/api/customers/exists?email=${encodeURIComponent(email)}`);
return (await res.json()).exists;
}
});
// Calculation and validation: the shipping price for a postcode, null where you don't deliver
const prices = new Map(); // one request per postcode serves both the calculated value and the validator
registerFunction({
name: "shippingCost",
isAsync: true,
func: async ([postcode]) => {
if (!postcode) return 0;
if (!prices.has(postcode)) prices.set(postcode, fetch(`/api/shipping?postcode=${encodeURIComponent(postcode)}`).then(r => r.json()));
return (await prices.get(postcode)).price;
}
});
routes/examples/async-functions.php · sjs:async-functions.server
View on GitHub
// GET /api/customers/exists?email= — answers emailExists()
Route::get('/api/customers/exists', function (Request $request) {
$email = Str::lower(trim((string) $request->query('email')));
return ['exists' => DB::table('customers')->where('email', $email)->exists()];
});
// GET /api/shipping?postcode= — answers shippingCost(): the longest matching postcode prefix wins,
// { "price": null } when none matches (the form shows "We don't deliver to this postcode yet")
Route::get('/api/shipping', function (Request $request) {
$postcode = Str::upper(str_replace(' ', '', (string) $request->query('postcode')));
// only a whole German (10115) or UK (SW1A 1AA) postcode gets a price, not anything that starts with a prefix
if (! preg_match('/^(\d{5}|[A-Z]{1,2}\d[A-Z\d]?\d[A-Z]{2})$/', $postcode)) {
return ['price' => null];
}
$rate = DB::table('shipping_rates')->get()
->filter(fn ($rate) => str_starts_with($postcode, $rate->postcode_prefix))
->sortByDesc(fn ($rate) => strlen($rate->postcode_prefix))
->first();
return ['price' => $rate ? (float) $rate->price : null];
});