for(var i = 0; i < res.length;i++){
var info = res[i];
var fpath = attach_root_dir+'/'+picker_id+'/'+article_data._id+'/'+info.fileName;
dlog(fpath);//位置1
nodeRequire('fs').exists(fpath, function (exists) {
dlog(fpath);//位置2
});
}
这段代码没贴全。
大致的作用就是从数据库里面循环读取附件列表,然后根据每个附件的信息,路径,去判断这个附件的文件是否存在。
现在的问题是,位置2得到的fpath变量永远都是同一个。
也就是说,外层的fpath无法正确的传递到位置2。因为异步执行的原因。如何解决这个问题呢?
PHPz2017-04-17 14:31:24
你沒有問原因不過我還是說一下原因吧。
fpath變數只是一個變數(引用),而你傳遞的回呼函數只知道:「哦,到時我可以去獲得(引用)fpath的值」。
關鍵在於你傳遞函數時,傳遞的只是一個未執行的函數,函數裡有fpath這一個變量,由於未執行,並未獲得當前值。
等非同步函數要去取得的時候,fpath的值已經是最後一個了。
假設問題為:
var a = [1,2,3,4,5,6,8]
for (var i = 0; i < a.length; i++) {
var c = a[i]
setTimeout(function(){
console.info(c);
}, 100)
}
解法一:(原始解法)
解法也很簡單,上面說了當時的函數沒有執行,我們可以創建一個函數執行一部分,用另外一個(新的函數的)變數存起來。
var a = [1,2,3,4,5,6,8]
for (var i = 0; i < a.length; i++) {
var c = a[i]
;(function(c){
setTimeout(function(){
console.info(c);
}, 100)
})(c)
}
解法二:(es6解法)
var a = [1,2,3,4,5,6,8]
for (var i = 0; i < a.length; i++) {
let c = a[i]
setTimeout(function(){
console.info(c);
}, 100)
}
PHP中文网2017-04-17 14:31:24
首先,fs
模組,判斷檔案是否存在有兩個方法,一個是fs.exists(path, callback)
,有一個非同步回調函數;還有一個是fs.existsSync(path)
,這個方法是同步的,傳回一個bool值。
然後是你這裡的問題,是由於fpath
出現在了回調函數的外部作用域中,造成了fpath總是同一個。
所以,有兩個方法可以解決這個問題:
1.使用fs.existsSync(path)
,使用同步的方式
2.閉包:
(function(fpath){
nodeRequire('fs').exists(fpath, function (exists) {
dlog(fpath);//位置2
});
}(fpath))
天蓬老师2017-04-17 14:31:24
就是一個基礎的閉包問題, 解法有二:
node版本0.x.x,在迴圈中寫立即執行函數:
for(var i = 0; i < res.length;i++){
+function(i){ var info = res[i];
var fpath = attach_root_dir+'/'+picker_id+'/'+article_data._id+'/'+info.fileName;
dlog(fpath);//位置1
nodeRequire('fs').exists(fpath, function (exists) {
dlog(fpath);//位置2
});
}(i);
}
node版本大於4.x.x+,把var 改為let:
for(let i = 0; i < res.length;i++){
var info = res[i];
var fpath = attach_root_dir+'/'+picker_id+'/'+article_data._id+'/'+info.fileName;
dlog(fpath);//位置1
nodeRequire('fs').exists(fpath, function (exists) {
dlog(fpath);//位置2
});
}