增强单页应用操作体验的一个重要思路就是增加本地(浏览器)缓存的处理机制。
以 pageno
为键缓存资源列表数据
用页码切换pageNoChange
来做页面内容刷新当前页面的数据
pageNoChange
分成三步走:
loadError = true
模版显示当前资源列表vm.list
的数据
vm.list
为undefined
时pageNoChange
vm.list
是数组时
此篇文章是在下为公司内部交流所写。整理后放入私人博客供参考。
This makes each component as a blackbox following the golden rule separation of concerns.
Here is a good article in Angular 1.5 official docs on Component-based application architecture.
The rules of using API for component interaction looks promising at first look, but we will soon have problems with it. Below is a common component tree of a complex view. Think that each box is a component (and each of them may also be consisted with smaller components).
There are various ways of doing component interactions in a complex app with angular 1.x. One problem is that we don’t have a best practice guideline on how to do data flow and event handling. To name a few possible ways:
$scope
chain. This may be the most common way of event handling in our app right now. The issues of using it:
Here are some of my suggestions after listing all kinds of these component interaction solutions:
$scope
for event handling from now onIn my opinion, what we need for now is a standalone messaging/component interaction data service to let the major components interact with each other. observer pattern could be a solution, but here I want to propose the use of RxJs into our app.
I don’t want to explain reactive programming deeply since this email could be a paper. You may find the following articles worth reading:
Angular 2 also has built-in RxJs usages in its http-client.
The key component of a reactive programming library is the Observable
object. An Observable
is essentially a data stream of values in time. In our case, the most important usage is to construct new global event streams, so that we could subscribe to them, and react to the new values.
The idea is quite similar to the observer pattern. However, the observer pattern is just an callback factory to be triggered sequentially when a new event emits. The Observable
object also provides some other flexible functionalities:
We could use RxJs/Observable in Angular 1.x system as an global Event manager service. Different components could create their own event streams (observables) and register in the manager with identifiers, which means we store all global event streams which may be used in different component in a key-value pairs map. So the subscribers could fetch the observables with keys, transform them into new Observables and then attach callbacks to the events.
借助于 ES7 的 async
语法,我们可以方便的使用 Promise 来书写优美的异步调用代码。
不过现有的 Node 版本,大部分的异步函数都还是回调函数方式接口的,比如 fs.read(fd, buffer, offset, length, position, callback)
。
笔者认为,使用 Promise
而不是回调函数的一大优势是: 将函数调用的责任转移到了使用异步函数者身上,而不是转嫁到异步函数去负责调用函数。
对于异步函数,我们其实最关心的是它的返回结果,然后根据结果做一些有用的事情。这样的调用才是更自然,符合直觉的编程方式。
好消息是,通过 Node 新版本原生支持的 Promise
类,我们可以很方便的将一个回调函数接口的函数转化成 Promise
版本的接口。
以最简单的 setTimeout
为例,我们使用它的一大作用是在当前的异步调用环境中加一个等待时间,然后接下来做一些别的事情。
function foo() {
setTimeout(() => {
doSomething1();
setTimeout(() => {
doSomething2();
}, 100);
}, 100);
}
上面的形式就是回调函数经常会出现的问题。借助 Promise
, 我们可以用下面的方式来改写:
// Returns a promise which will resolve in $milliseconds
function delay(milliseconds) {
return new Promise(res => {
setTimeout(res, milliseconds);
});
}
async function awesomeFoo() {
await delay(100);
doSomething1();
await delay(100);
doSomething2();
}
是不是看起来清爽很多了呢?
对于更复杂一点的 fs.readFile(file, callback)
函数,我们可以将其以类似的方式改写成 Promise
版本。
传统方式调用如下
function foo() {
fs.readFile('/etc/passwd', (err, data) => {
if (err) throw err;
console.log(data);
});
}
改写后:
// Promise based fs.readFile
function awesomeReadFile(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
if (err) reject(err);
resolve(data);
});
});
}
async function awesomeFoo() {
try {
const data = await awesomeReadFile();
console.log(data);
} catch (err) {
throw err;
}
}
最后,希望新版本的 Node
可以提供原生的 Promise
API。别做梦了