低代碼平台中的數據連接方式(上)

語言: CN / TW / HK

1. 前言

在早幾年,“拖拽式 H5 營銷頁製作工具” 曾經是前端界的一大熱門方向,這類工具的特點是可以通過拖拽的方式來生成帶有各種酷炫效果的靜態營銷頁,這類工具可以看作是現今“低代碼平台”的前代產品。

而在當今的互聯網中,以 “靜態” 方式承載內容的頁面越來越少。也就是説,“拖拽生成靜態頁”這樣單純的能力在現代應用的開發過程中能覆蓋的場景是非常少的,這就催生了以 “能夠對接動態數據” 為特徵的第二代低代碼產品。

為了滿足 “對接動態數據” 這一基礎訴求,低代碼平台經歷了從最初簡單 API 對接模式到完整的數據模型接管的發展過程,而完整的數據模型接管能力,也是現今各低代碼廠商發力深耕的方向之一。

低代碼平台中可選的數據連接方式有很多種,各種方法產生和成熟的時期不同。而在現今互聯網主流的業務模式下,這些方法在不同的場景下都有其適用的範疇。

關於低代碼平台的數據鏈接方式這個話題,我們將分為上下兩篇內容進行分享:

  • 在(上)篇中,我們將介紹 經典的單 API 通信數據連接方式 - 簡單的單 API 連接方式存在的問題 - 相應解決方案

  • 在(下)篇中,我們將介紹在低代碼時代發展起來的 API 編排 - FaaS - 數據庫直連等新型方案

2. 傳統手工模式下動態數據的獲取和渲染

在互聯網頁面開發中,動態數據的獲取 - 渲染可以説是一個最基本的 “需求”。在多數情況下,當瀏覽器向服務端請求一個頁面的時候,服務端返回的會是一個頁面的 “框架”,而頁面的具體內容會由頁面中的 JavaScript 腳本向服務端發起 ajax 請求並將返回結果渲染到頁面上。

在 jQuery 盛行時期的互聯網開發中,“從服務端獲取數據並渲染到頁面上” 的代碼可能是這樣的(代碼示例來源:jQuery官網, http://api.jquery.com/jquery.ajax/):

var menuId = $( "ul.nav" ).first().attr( "id" );
var request = $.ajax({
url: "script.php",
method: "POST",
data: { id : menuId },
dataType: "html"
});


request.done(function( msg ) {
$( "#log" ).html( msg );
});


request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});

而在 MVVM 框架經過數年角逐並形成 React / Vue 二分天下之勢力的當今互聯網開發中,“從服務端獲取一段數據並在頁面中渲染出來” 的代碼可能是這樣(React,代碼示例來源:http://dev.to/antdp425/react-fetch-data-from-api-with-useeffect-27le)

// 1. Import *useState* and *useEffect*
import React, {useState, useEffect} from 'react';
import './App.css';


function App() {
// 2. Create our *dogImage* variable as well as the *setDogImage* function via useState
// We're setting the default value of dogImage to null, so that while we wait for the
// fetch to complete, we dont attempt to render the image
let [dogImage, setDogImage] = useState(null)


// 3. Create out useEffect function
useEffect(() => {
fetch("http://dog.ceo/api/breeds/image/random")
.then(response => response.json())
// 4. Setting *dogImage* to the image url that we received from the response above
.then(data => setDogImage(data.message))
},[])


return (
<div className="App">
{/* 5. Using *dogImage as* the *src* for our image*/}
{dogImage && <img src={dogImage}></img>}
</div>
);
}


export default App;

或這樣(Vue,代碼示例來源:http://cn.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html)

new Vue({
el: '#app',
data () {
return {
info: null
}
},
mounted () {
axios
.get('http://api.coindesk.com/v1/bpi/currentprice.json')
.then(response => (this.info = response))
}
})

無論是早期 jQuery 還是現今已經成為互聯網頁面基礎設施的 MVVM 框架,“動態數據連接” 的方式大抵是 “向某個後端接口發送請求然後等待數據返回”。

而在進行前端業務組件的 “低代碼” 形式封裝時,低代碼框架和平台的建設者們第一步做的通常也是將組件需要的 API 請求抽取成配置項。

3. 低代碼最初的數據連接方式 

—— 通過 API URL 進行數據通信

如圖 1 中的 CRUD 組件,在組件配置中填寫數據列表的獲取接口和新增數據提交接口後,組件初始化時會向填寫的 API 發起網絡請求,新增記錄時也會使用配置的新增數據提交接口。

這樣一來,通過一個簡單的配置項就能夠實現原本需要書寫大段代碼的功能。

圖 1  為 CRUD 組件配置異步請求接口

這種通過 API 配置即可實現數據連接的方案,很簡單也很美好,在低代碼平台建設的初期往往也會被作為 “最小可用版本” 的首選方案。

但是在實際落地場景中,這種最簡單的方案往往會遇到兩個問題:

    • 一是前端需要的數據格式和後端返回的數據格式不匹配的問題。

    • 二是前端最經典的問題 —— 跨域問題。

下面我們結合低代碼平台在實際落地中的場景來看一看上述兩個問題的產生緣由。

4. 問題產生 —— 低代碼平台實際落地中的阻礙

    4.1 前後端數據格式不匹配問題

在低代碼平台實際業務落地的過程中,多數時候面對的場景都不是 “從零開始” 用低代碼平台去搭建一個應用,而是 “將某些業務模塊逐步遷移到低代碼平台”。這就意味着低代碼平台需要和許多已經在線上運行的舊接口打交道。

在業務逐步往低代碼遷移的過程中,很長一段時間內可能是如圖 2 所示的狀態 —— 低代碼平台需要去連接一些仍在支持線上業務的接口,同時這些接口也仍在支撐着運行中的線上業務,這就意味着不能為了 “接入低代碼平台” 而貿然對這些接口進行改造。

圖 2  低代碼平台連接現有的舊接口

而從低代碼平台中的角度來説,通用組件為了保證其通用性,必然需要對接口返回的數據格式有一個統一的規約。例如在 低代碼平台愛速搭 的組件體系(即 AMIS)中,就規定了數據接口的返回格式需要符合以下格式,可以參考一下鏈接:

http://aisuda.bce.baidu.com/amis/zh-CN/docs/types/api

{
"status":0,
"msg":"",
"data":{
...其他字段
}
}

而正如前文所説,低代碼平台很多時候需要去連接舊的線上接口,這些接口返回的數據格式往往不符合低代碼平台的要求,並不太可能 “為了適配低代碼平台” 而去進行專門改造。

那麼除了為低代碼平台定製開發一套專用接口外,有沒有辦法能夠既享受低代碼平台帶來的便利,又能減免後端接口的改造成本呢?

這個問題我們將在本篇的第 5 到第 7 節做統一解答。我們先來看一看另一個前端經典問題 —— 跨域問題的產生。

    4.2 跨域問題

如前文的圖 2 所示,當前線上業務的域名是 a.xxx.com ,而低代碼平台的域名是 b.xxx.com,這意味着舊的線上接口可能無法被來自 a.xxx.com 的前端請求直接訪問,而如果要求後端改造現有接口或服務器配置來多兼容一個域名,也可能導致不可控的成本和安全隱患。

“跨域問題” 的實際效果如圖 3(圖片來自百度搜索),前端開發人員都非常熟悉的 blocked by CORS policy 報錯。

圖 3  前端向不同域名發送的請求由於跨域被瀏覽器攔截

為此,低代碼平台愛速搭提供了“瀏覽器端的數據映射機制”、“瀏覽器端請求/接收適配器”和“ API 代理”等幾項能力來協作解決第 4 節提到的這兩個問題。

藉助這些能力,可以在後端接口不做任何改動的情況下實現低代碼平台對業務的平滑接入。

5. 瀏覽器端的數據映射機制

數據映射,指的是在接口發送 / 接收前將原始字段的值賦給目標字段,例如後端返回的格式是 {a: 'xxx', b: 'ooo'} 而前端組件需要的格式是  {c: 'xxx', b: 'xxx'},在數據映射中配置 c: ${a} 就可以將接口返回的數據格式化成前端需要的格式。

在愛速搭中,數據映射分為瀏覽器端數據映射和服務端數據映射。關於服務端數據映射,我們會在本文的 7.2 節予以説明。

瀏覽器端數據映射在愛速搭中的配置界面如圖 4 所示,可以在面板上打開 “數據映射” 開關並以 key: value 的格式進行數據映射配置。

圖 4  用數據映射解決數據格式匹配問題

需要注意的是這個 “映射” 是在數據接口請求發送之前 / 返回之後在瀏覽器端進行的格式化,所以設置之後觀察接口返回數據也不會看到任何改變。

該能力是在 AMIS 框架中實現的,愛速搭對其進行了可視化封裝,關於 AMIS 框架中的實現,可以閲讀官方文檔:

http://aisuda.bce.baidu.com/amis/zh-CN/docs/concepts/data-mapping

6. 瀏覽器端請求 / 接收適配器

在簡單的映射無法滿足複雜的數據格式化需求時,愛速搭還提供了通過 js 函數來對數據格式進行處理的方式。

如圖 5,可以在 CRUD 組件的 API 配置處編寫 js 函數代碼,在請求發送 / 請求結果返回時,這些自定義函數會被調用來對數據進行格式化,這個 “格式化” 的過程也是在瀏覽器端執行的。

圖 5  在愛速搭平台 中編寫適配器函數

該能力同樣是在 AMIS 框架中實現的,具體見 AMIS 文檔:

http://aisuda.bce.baidu.com/amis/zh-CN/docs/types/api#%E9%85%8D%E7%BD%AE%E8%AF%B7%E6%B1%82%E9%80%82%E9%85%8D%E5%99%A8

7. API 代理

跨域問題產生的根本原因是瀏覽器對跨域訪問的限制 。在低代碼平台實際落地的場景中,低代碼平台和業務往往部署在不同的域名下,並且業務方也通常不可能為了接入低代碼平台而增加額外的跨域訪問白名單或獨立部署一套同域下的低代碼平台。故而 “跨域問題” 也是低代碼平台落地的一大阻礙。

    7.1 統一 API 代理方案

處理跨域問題的方案有很多種,愛速搭採用了統一 API 代理的方案,通過後端的代理服務來對 API 請求進行統一轉發,從而規避了跨域請求被瀏覽器攔截的問題。

下面我們來看一看愛速搭中 API 代理服務的具體實現。

在愛速搭中,默認情況下組件中填寫的接口配置在不是由前端直接向服務端發起請求,而是經由愛速搭的 API 代理服務進行轉發後再將實際後端接口返回的數據通過代理服務返回到前端。

如圖 6,在 Form 組件上配置了一個保存接口的 url。

圖 6  Form 組件上配置的保存接口 url

實際發起請求時訪問的 url 如圖 7:

圖 7  實際發起請求時通過 Proxy 接口

從原理上説,愛速搭 API 代理的運行方式是在編輯保存階段將頁面中的 API 抽出來存到一個數據庫表中,並給每個 API 生成一個標識,然後在運行時實際訪問的是類似  api/proxy/:apiId 這樣的接口,再由後端服務通過 apiId 找到實際的接口 url,轉發請求並等待遠端返回後再將結果返給前端。API 代理在當前市面上的低代碼平台中是一個 “標配” 服務。

跨域問題只存在於前端瀏覽器層面,這種通過後端接口轉發請求的方式,從根本上規避了前端跨域問題的產生

    7.2 後端數據映射及後端請求 / 接收適配器

除了簡單的轉發,愛速搭的 API 代理還提供了後端執行的數據映射和適配器等機制。在應用設置 - 接口 - 全局接口適配器中可以為 API 代理配置全局適配器,如圖 8 所示:

圖 8  全局適配器

而在愛速搭中如果希望為單個 API 配置映射和適配器,可以 API 中心新建單個接口並填寫相應配置項,如圖9所示:

圖 9  為單個接口配置設置參數轉換和適配器

為什麼有了服務端執行的數據映射和請求 / 接收適配器,還需要前面所説的瀏覽器端執行方案呢?

原因有兩點:

  • AMIS 作為一個開源項目,在許多時候可能會被作為獨立依賴引入到項目中,在沒有 API 代理機制的情況下前端方案可以解決一部分問題。

  • 如果在配置項中指定請求為 raw: 則網絡請求不會經過 API 代理髮送,這時如果需要對數據進行格式化,則需要藉助前端方案。

此外,愛速搭還開放了自定義 header 等請求信息的配置能力,由於篇幅所限,本文不再一一贅述,有興趣的讀者可自行查閲愛速搭或 AMIS 官方文檔。

8. 小結

通過上述幾個方案,愛速搭解決了低代碼平台在實際落地時的改造成本和溝通成本問題,使得業務不再需要為了享受低代碼平台的便利而進行可能帶來更多麻煩的改造工作。

但基於單 API 通信的方案仍然依賴於 “現成” 的接口。如果是全新的功能,依舊需要由後端開發人員以傳統模式進行 API 的開發和部署上線 —— 當然,並不能武斷地認為這種方案就應當被淘汰,因為在實際生產環境中,許多通用型的接口已經作為穩定的數字資產被沉澱下來,作為open api 提供給業務方使用,以 API 方式來調用這些通用接口,顯然最合適不過。

那麼在後端接口也 “不存在” 的情況下,有沒有辦法能夠通過低代碼平台快速開發上線應用呢?答案是肯定的。為此愛速搭平台提供了 API 編排,FaaS 和數據庫直連方案,我們將在本文的(下)篇中介紹這些新型的技術方案。

  往期推薦  

:link:

可視化神器背後的奧祕

6000字,詳解數據倉庫明星產品背後的技術奧祕

“智感超清”之HDR技術落地實踐