作者s25g5d4 (function(){})()
看板Ajax
标题Re: [问题] 延後执行的问题
时间Sat Aug 22 11:27:47 2015
前阵子因为试用 Visual Studio Code 与 Electron 写了一个小专案
刚好写到跟你问题一模一样的东西,code 在此
https://github.com/s25g5d4/SlideShow/blob/master/scripts/main.js#L76
我使用 mrbigmouth 板友提到的 async.js 套件,你可以参考一下
configs.images 是一个包含数个字串的阵列 (就是图档档名)
loadImg 函数会试着把这些图档载入,具体行为是
1. 建立 Image() 并检查是否有 cache (透过检查 complete 属性)
2. 挂上 onload 事件
3. 挂上 onerror 事件
imgDone 函数是当 configs.images 里所有图档都载入後
过滤错误的图片,将页面初始化并开始绘制画面
--
若不引入 async.js 套件,可以参考 dianwu 板友的解法
只是不需要多 imgReady 变数
直接检查 array.length 跟 m.length 就好
另外一个做法是把 dosomething() 改写成
function dosomething(val, array) {
array.push(val);
// 如果图档还没全部载入,就先退出 function
if (array.length < m.length) return;
// 若执行到这边代表图档已全部载入
// 接着做原本该做的事
// ...
}
原本 onload 事件改成
img.onload = function () {
//图片读取好後进行一些处理再return回来
var t = doImg(this);
i.forEach(function(p){
//将图片及资讯push进array
dosomething({
img : t,
p1 : p,
p2 : [p[0] + t.width, p[1] + t.height],
p3 : t.pos[1] + p[1]
}, array);
});
};
--
另外 dianwu 板友提到「不建议在回圈中直接宣告 function」
我的看法是「不建议使用匿名函数」
这并不是代表不要使用 callback 或 Immediately-invoked function expression
注:即 (function () { /* some code */ }())
而是使用 function expression (以下简称 func expr) 时一定要指定函数名称
在侦错的时候浏览器开发工具或 Node.js 大多会提供 function call stack
如果用一堆匿名函数,错误讯息会看得很痛苦
http://craigshoemaker.net/images/command-prompt-node-error.png
有看到 at <anonymous>:1:55 吗?
如果 func expr 在内部须呼叫 func expr 本身
使用具名函数便可以以该名称存取自己
范例:
setTimeout(function doAnimation() {
// do something
setTimeout(doAnimation, 100);
}, 100);
而且不会造成任何变数污染问题
doAnimation 名称只在 doAnimation 函数内可见
即使在与 setTimeout 同 scope 的地方也不可见 doAnimation
所以不用担心会盖掉同样名称的变数
--
其实我不知道为什麽 scope 会有问题
除非把 function 提到回圈所在 scope 外面才会造成 scope 不同
以下两个例子的 scope 是一样的
========
array.forEach(function forEach(e, i) {
// do something
});
========
var doSomething = function doSomething(e, i) {
// do something
};
array.forEach(doSomething);
=======
在大多数情况下, callback function 应该不需要离 iteration 太远
顶多拉出来变成另一个变数,这样还是会在同一个 scope 下啊 XD
如果有必要让 callback 与 iteration 所在 scope 不同
那应该是这个 callback 可以在多个地方重复使用
这种情况下就需要注意 scope 的问题
javascript 是 static(lexical) scope 的语言
scope 只与 function 定义的地方有关,与执行期 call stack 无关
--
1F:→ HornyDragon: 昨天看到就秒下载了07/27 22:36
2F:推 jupto: 好色龙也喜欢人味重的了? 我还以为拟人度高的都不行呢07/27 22:40
3F:→ ykes60513: 你误会了 好色龙看上的是那狼人07/27 22:42
4F:推 HornyDragon: 你看三楼就很懂07/27 22:43
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.174.152.40
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Ajax/M.1440214075.A.C46.html
5F:推 dianwu: 详细的解说,我印象中如果在回圈内的function 直接使用上 08/22 12:31
6F:→ dianwu: 层的变数很可能在执行时与一开始的想法有出入,特别又是im 08/22 12:31
7F:→ dianwu: g onload,但早上回文时没有再实做确认一次,也许错了:) 08/22 12:31
你说的其实不是 scope 问题
是因为 async call 的关系,抓到的是被覆盖掉的值
解决方法是建立一个新的 scope, 也就是 closure
var i;
for (i = 0; i < 5; ++i) {
setTimeout(function () {
alert(i);
}, 1);
}
这个范例会弹出五个 5, 而不是预期的 0, 1, 2, 3, 4
var i;
for (i = 0; i < 5; ++i) {
(function (t) {
setTimeout(function () {
alert(t);
}, 1);
}(i));
}
这样才是预期的 0, 1, 2, 3, 4
--
酷一点的解法
var i;
for (i = 0; i < 5; ++i) {
setTimeout(alert.bind(this, i), 1);
}
--
这应该是讲到烂掉的问题了 :P
※ 编辑: s25g5d4 (1.174.152.40), 08/22/2015 13:13:05
8F:推 m2251000: 谢谢大大详细讲解!检查快取那一步让我学到了新东西! 08/22 23:18