33 views

封装的API调用前后分离模型

By | 2019年8月4日

Ajax 和异步处理
调用API访问数据采用Ajax方法,这是一个异步过程。处理异步进程的最基本方法是事件或回调。事实上,这两种方法在原则上是相似的。当调用异步进程时,它们都需要传入在异步进程结束时调用的接口。例如,jQueryAjax的成功是一个典型的回调参数。但是,建议使用jquery进行异步处理,并使用Promise处理。

promise处理也通过注册回调函数来完成。jquery的proise和es6标准promise有些不同,但它们在当时是兼容的,通常称为nable。jquery的proise不提供.catch()接口,而是提供自己的定义。完成()失败()和始终()以方便使用的方式注册回调。它是以事件方式注册的(也就是说,它可以注册同一类型的多个处理程序,这些处理程序将在触发时触发)

当然,更直观的方法是使用ES2017带来的异步/等待模式,它可以用同步代码的形式编写异步代码,当然也有一些坑。对于前端工程师来说,最大的缺陷是有些浏览器不支持它,需要翻译,所以如果不构建前端代码,通常最好使用ES5语法兼容性(jquery的proise支持ES5,但标准Promise只能在ES6之后使用)。

自己封装工具函数
在处理Ajax的过程中,尽管有现成的库(如jquery)。Ajax、AXIOS等),毕竟它是为通用目的设计的,使用起来仍然很繁琐。在项目中,调用API的过程几乎相同。如果设计得当,即使是错误处理也是一样的。因此,实际上可以进一步封装项目中的Ajax调用,以便在项目中使用。如果界面模式发生变化,则更容易修改。

例如,当前接口需要使用post方法调用(不考虑restful),参数必须包括操作,返回的数据以json模式提供,如果有错误,只要不是服务器异常,包括cod,特定的json数据就会返回。e不等于0和可选的消息属性。

那么用 jQuery 写这么一个 Ajax 调用,大概是这样

const apiUrl = “http://api.some.com/”;

jQuery
.ajax(url, {
type: “post”,
dataType: “json”,
data: {
action: “login”,
username: “uname”,
password: “passwd”
}
})
.done(function(data) {
if (data.code) {
alert(data.message || “登录失败!”);
} else {
window.location.assign(“home”);
}
})
.fail(function() {
alert(“服务器错误”);
});
初步封装

在同一个项目中,此类Ajax调用基本上与数据部分和的其他部分不同。Don回调,因此封装一次将大大减少以这种方式封装的代码量。

function appAjax(action, params) {
var deffered = $.Deferred();

jQuery
.ajax(apiUrl, {
type: “post”,
dataType: “json”,
data: $.extend({
action: action
}, params)
})
.done(function(data) {
// 当 code 为 0 或省略时,表示没有错误,
// 其它值表示错误代码
if (data.code) {
if (data.message) {
// 如果服务器返回了消息,那么向用户呈现消息
// resolve(null),表示不需要后续进行业务处理
alert(data.message);
deffered.resolve();
} else {
// 如果服务器没返回消息,那么把 data 丢给外面的业务处理
deferred.reject(data);
}
} else {
// 正常返回数据的情况
deffered.resolve(data);
}
})
.fail(function() {
// Ajax 调用失败,向用户呈现消息,同时不需要进行后续的业务处理
alert(“服务器错误”);
deffered.resolve();
});

return deferred.promise();
}
而业务层的调用就很简单了

appAjax(“login”, {
username: “uname”,
password: “passwd”
}).done(function(data) {
if (data) {
window.location.assign(“home”);
}
}).fail(function() {
alert(“登录失败”);
});
更换 API 调用接口

上面的封装统一了调用接口和返回的数据,删除了项目接口协议的大部分内容,并且每个调用中唯一需要处理的就是纯业务。

现在,项目团队决定不使用jquery的Ajax,而是使用AXIOS来调用API(AXIOS不一定比jquery更好,这里只是一个例子),所以您只需要修改appajax()的实现。不需要修改所有业务呼叫。

假设当前目标环境仍然是ES5,则需要第三方承诺。Bluebird在这里被提议与本地Promise接口兼容(在HTML中引入,而不是直接在JS代码中引入)。

function appAjax(action, params) {
var deffered = $.Deferred();

axios
.post(apiUrl, {
data: $.extend({
action: action
}, params)
})
.then(function(data) { … }, function() { … });

return deferred.promise();
}
这种封装使用AXIOS来实现Web API调用。但是,为了维护原始接口(jquery promise对象提供)。完成(),。失败()和。始终()事件处理),Appajax仍然必须返回jquery promise。通过这种方式,即使不再需要jquery,它仍然需要在这里使用。

jquery应该在项目中使用还是不使用?阅读为什么本机javascript会取代jquery?

去除 jQuery

在这里使用jquery总是让人觉得它在你的背上,你想摆脱它。有两种方法

修改业务中的所有调用,删除。完成(),失败()和。始终(),并更改为。然后()。这一步需要很多工作,但基本上是无痛的,因为jQueryPromise本身支持。然后()。但有一件事需要特别注意。稍后,它表明,编写一个与jQueryPromise接口兼容的适配器并不是一个很小的工作负载,但关键是要完全测试和避免错误。

在上面提到的第一种方法中,有一件事需要特别注意。然后()和。done()系列函数的处理方式不同。然后根据承诺的特点设计(),返回另一个承诺对象;done()系列函数根据事件机制实现,返回原始Promise对象。因此,当您像下面这样修改代码时,应该注意它。

appAjax(url, params)
.done(function(data) { console.log(“第 1 处处理”, data) })
.done(function(data) { console.log(“第 2 处处理”, data) });
// 第 1 处处理 {}
// 第 2 处处理 {}
简单的把 .done() 改成 .then() 之后(注意不需要使用 Bluebird,因为 jQuery Promise 支持 .then())

appAjax(url, params)
.then(function(data) { console.log(“第 1 处处理”, data); })
.then(function(data) { console.log(“第 2 处处理”, data); });
// 第 1 处处理 {}
// 第 2 处处理 undefined
如上所述,正确的方法是合并多个done或在中返回数据。然后()处理程序:

appAjax(url, params)
.then(function(data) {
console.log(“第 1 处处理”, data);
return data;
})
.then(function(data) {
console.log(“第 2 处处理”, data);
});
使用 Promise 接口改善设计

我们的appajax()接口也可以设计为Promise实现,这是一个更通用的接口。您可以使用ES2015+功能,也可以使用jquery promise或bluebird等三方库提供的promise。

function appAjax(action, params) {
// axios 依赖于 Promise,ES5 中可以使用 Bluebird 提供的 Promise
return axios
.post(apiUrl, {
data: $.extend({
action: action
}, params)
})
.then(function(data) {
// 这里调整了判断顺序,会让代码看起来更简洁
if (!data.code) { return data; }
if (!data.message) { throw data; }
alert(data.message);
}, function() {
alert(“服务器错误”);
});
}
但是现在前端已经有了构建工具,您可以使用ES2015+来配置babel,或者使用typescript…总之,有很多选择,而且它们很方便书写。因此,我们不必将设计局限于ES5支持的内容。所以我们可以考虑使用promise+async/await来实现它。

async function appAjax(action, params) {
// axios 依赖于 Promise,ES5 中可以使用 Bluebird 提供的 Promise
const data = await axios
.post(apiUrl, {
data: $.extend({
action: action
}, params)
})
// 这里模拟一个包含错误消息的结果,以便后面统一处理错误
// 这样就不需要用 try … catch 了
.catch(() => ({ code: -1, message: “服务器错误” }));

if (!data.code) { return data; }
if (!data.message) { throw data; }

alert(data.message);
}
使用技巧。捕获()以避免尝试…上面代码中的catch()在从未用try catch实现的async/await语法中提到。
当然业务层调用也可以使用 async/await(记得写在 async 函数中):

const data = await appAjax(“login”, {
username: “uname”,
password: “passwd”
}).catch(() => {
alert(“登录失败”);
});

if (data) {
window.location.assign(“home”);
}
对于多次 .done() 的改造:

const data = await appAjax(url, params);
console.log(“第 1 处处理”, data);
console.log(“第 2 处处理”, data);

小结
本文以包装Ajax调用为例,似乎在讨论异步调用。但是我想告诉你的是:如何封装一个常用的函数来实现代码重用和更简洁的调用;以及封装过程中需要考虑的问题-向前和向后兼容性,在封装工具函数时,我们应该尽量避免绑定具有特定的工具功能。固定,接近公共标准-我不知道你是否有任何经验。

本文编辑于2019年08月4日,属于云漫网络原创内容,由特约作者(云漫网络编程技术)首发在win-man.com,云漫网络每日更新发布行业原创内容,转载请注明出处。否则属侵权行为一定追究责任。

作者:云漫网络编程技术
本文转载于:http://win-man.com
本文关键词:PHP,高防CDN,加速CDN,TTCDN

发表评论

电子邮件地址不会被公开。 必填项已用*标注