Develop Online
AirCode provides an in-browser IDE that allows the development process to be completely online without downloading any dependency and configuration.
Runtime
AirCode's functions use JavaScript and the runtime environment is Node.js.
If you are unfamiliar with these two languages, it is recommended to go through JavaScript Tutorial and Node.js Doc to study.
Create a Function
Click + above the function list, enter a name, and click ✓ to create a Node.js function.
All cloud functions have .js
as the extension, and you can also modify it to create other types of files, such as .json
, .txt
, etc. These non-.js
files will not be treated as cloud functions, that is, no online URL API will be generated. They are generally used to store configurations and referenced by require
in other cloud functions.
Template and Parameter
module.exports = async function(params, context) {
return {
message: 'Hi, AirCode.',
};
}
module.exports = async function(params, context) {
return {
message: 'Hi, AirCode.',
};
}
Every cloud function needs to module.exports
an async
function, and it contains two variables: params
and context
.
params
is the parameter passed when requesting the functioncontext
contains the context information of the request and some helper methods
Note
If an async
function is not exported through module.exports
, it will not be able to take online requests. This is normally used as private functions, see: Private Functions for more details.
for example:
module.exports = async function(params, context) {
return {
message: params.message,
method: context.method,
};
}
module.exports = async function(params, context) {
return {
message: params.message,
method: context.method,
};
}
After deployment, access this function through curl with the request body:
curl -H "content-type:application/json" -X POST -d '{"message": "Hello World"}' \
https://sample.hk.aircode.run/hello
curl -H "content-type:application/json" -X POST -d '{"message": "Hello World"}' \
https://sample.hk.aircode.run/hello
will return:
{
"message": "Hello World",
"method": "POST"
}
{
"message": "Hello World",
"method": "POST"
}
Guide
- Learn how to retrieve POST Parameters and GET Parameters via
params
- Learn how to get and set HTTP Context via
context
Response
Every function's exports should have a return value, and this value will be returned as the Response Body.
Note
Circular references in the return value should be avoided, otherwise it will cause output errors.
Object Response
The return value can be an object, and the object will be converted to JSON and returned as the Response Body.
module.exports = async function(params, context) {
return {
message: 'Hi, AirCode.',
};
}
module.exports = async function(params, context) {
return {
message: 'Hi, AirCode.',
};
}
The response body will be:
{
"message": "Hi, AirCode."
}
{
"message": "Hi, AirCode."
}
Steaming Response
You can return any readable stream as the response body, such as a file stream, a response from AI services, etc. The client can consume the stream in real time.
Here is an example of returning the response from OpenAI as a stream:
const OpenAI = require('openai');
const { OpenAIStream } = require('ai');
module.exports = async function(params, context) {
const { messages } = params;
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
// Get the OpenAI response
const response = await openai.chat.completions.create({
model: 'gpt-4',
stream: true,
messages,
});
// Transform the response into a readable stream
const stream = OpenAIStream(response);
// Return the stream as response, which can be consumed by the client
return stream;
}
const OpenAI = require('openai');
const { OpenAIStream } = require('ai');
module.exports = async function(params, context) {
const { messages } = params;
const openai = new OpenAI({
apiKey: process.env. OPENAI_API_KEY,
});
// Get the OpenAI response
const response = await openai.chat.completions.create({
model: 'gpt-4',
stream: true,
messages,
});
// Transform the response into a readable stream
const stream = OpenAIStream(response);
// Return the stream as response, which can be consumed by the client
return stream;
}
Handle Async Tasks
Because the exported function is async
, we recommend using await
to handle async tasks such as HTTP requests, Promise
tasks, etc.
module.exports = async function(params, context) {
// A sleep function return a Promise task
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
// Use `await` to handle the asynchronous tasks
await sleep(1000);
return {
message: 'Hello after sleeping 1 second',
};
}
module.exports = async function(params, context) {
// A sleep function return a Promise task
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
// Use `await` to handle the asynchronous tasks
await sleep(1000);
return {
message: 'Hello after sleeping 1 second',
};
}
Note
Because the cloud function is built upon serverless, if await
is not used to wait for the end of an async task, the task will be interrupted after the function returns and cannot continue to execute, and the result is also unpredictable.
e.g:
module.exports = async function(params, context) {
setTimout(() => {
// This text won't be logged
console.log('A log in async task');
}, 1000);
// After return, the setTimeout async task will be terminated
return {
message: 'Hi, AirCode.',
};
}
module.exports = async function(params, context) {
setTimout(() => {
// This text won't be logged
console.log('A log in async task');
}, 1000);
// After return, the setTimeout async task will be terminated
return {
message: 'Hi, AirCode.',
};
}
Error Handling
It is recommended to use try catch
to handle errors in functions, for example:
module.exports = async function(params, context) {
// Use `try catch` to handle errors
try {
const result = await someTask();
return {
result,
};
} catch (error) {
console.error('Error happened.');
return {
error: error.message,
};
}
}
module.exports = async function(params, context) {
// Use `try catch` to handle errors
try {
const result = await someTask();
return {
result,
};
} catch (error) {
console.error('Error happened.');
return {
error: error.message,
};
}
}
If an uncaught error occurs while the function is running, a 500 Internal Server Error
will be returned.
Guide
Timezone
The timezone in AirCode cloud functions is UTC±0 no matter which region the application is deployed in. If you have custom requirements for it, you can use dayjs
library.
// Require `dayjs` and its plugins to support custom timezone
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');
dayjs.extend(utc);
dayjs.extend(timezone);
module.exports = async function(params, context) {
const date = new Date();
// The default timezone is UTC±0
const defaultTimezone = date.toLocaleString();
// Use dayjs to set a custom timezone
const customTimezone = dayjs(date).tz('Asia/Shanghai').format('YYYY/MM/DD hh:mm:ss');
return {
defaultTimezone,
customTimezone,
};
}
// Require `dayjs` and its plugins to support custom timezone
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');
dayjs.extend(utc);
dayjs.extend(timezone);
module.exports = async function(params, context) {
const date = new Date();
// The default timezone is UTC±0
const defaultTimezone = date.toLocaleString();
// Use dayjs to set a custom timezone
const customTimezone = dayjs(date).tz('Asia/Shanghai').format('YYYY/MM/DD hh:mm:ss');
return {
defaultTimezone,
customTimezone,
};
}
Avoid Using Global Variables
AirCode's is running with multiple instances, and it will dynamically scale according to the traffic. It cannot guarantee that every request touches the same instance. Therefore, you should try to avoid using global variables, as this will lead to unexpected results.
e.g:
// Using global variables can lead to unexpected results
let someGlobalVar = 0;
module.exports = async function(params, context) {
// The original value of `someGlabalVar` is unpredictable
someGlobarVar += 1;
// An unexpected return value
return {
someGlobarVar,
};
}
// Using global variables can lead to unexpected results
let someGlobalVar = 0;
module.exports = async function(params, context) {
// The original value of `someGlabalVar` is unpredictable
someGlobarVar += 1;
// An unexpected return value
return {
someGlobarVar,
};
}
If there is a global variable storage requirement in the function, it is recommended to use a database, see: Database Introduction.
Delete a Function
Click the "More" button of a corresponding function, select Delete, and click OK in the pop-up window to delete the function.
Guide
- If the deleted function has already been deployed, you need to have another deployment to delete it, see: Deployment - Deploy the Deletion
- The deleted function will be moved to the recycle bin, which can be viewed and restored, see: Recycle Bin