[英]Promise won't resolve
我是Node的新手,但在解決異步Promise時遇到問題。 我的諾言沒有解決,我不確定自己做錯了什么。 我在理解Promise和回調方面仍然遇到困難,因此任何反饋都將有所幫助。
var filterFiles = function(){
return new Promise(function(resolve, reject){
fs.readdir(rootDir, function(err, files){
if(err) return console.log(err);
var task = function(file){
return new Promise(function(resolve, reject){
if(! /^\..*/.test(file)){
fs.stat(rootDir + '/' + file, function(err, stats){
if(stats.isDirectory()){
dirArray.push(file);
console.log(dirArray.length);
resolve(file);
}
if(stats.isFile()){
fileArray.push(file);
console.log(fileArray.length);
resolve(file);
}
})
}
})
};
var actions = files.map(task);
return Promise.all(actions).then(function(resolve, reject){
resolve({dirArray: dirArray, fileArray: fileArray});
});
})
})
}
filterFiles().then(function(data){
console.log(data);
var obj = {
fileArray: fileArray,
dirArray: dirArray
};
res.send(obj);
})
它至少看到三個錯誤:
當您擊中此if
語句if(! /^\\..*/.test(file)){
並且它不執行if
塊時,則永遠不會解決父承諾。
fs.stat()
上沒有錯誤處理,因此,如果在該調用中遇到錯誤,則將其忽略,並將嘗試使用錯誤的值。
您對fs.readdir()
調用中的錯誤處理不完整,並且會給您帶來永遠無法兌現的承諾(應拒絕時)。
對於健壯的解決方案,您真的不希望在同一代碼中混合使用Promise和回調。 這會帶來很多錯誤的機會,尤其是在錯誤處理方面(如您所見,您至少有三個錯誤-其中兩個在錯誤處理中)。
如果您要使用Promises,則在最低級別對您正在使用的異步操作進行承諾,並僅使用Promise控制您的異步代碼流。 我知道使相關的fs
操作實現承諾的最簡單方法是將Bluebird Promise.promisifyAll()
庫及其Promise.promisifyAll()
。 您不必使用該庫。 您可以改為為正在使用的異步操作手動編寫Promise包裝器。
這是使用Bluebird Promise庫的代碼版本:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
function filterFiles() {
return fs.readdirAsync(rootDir).then(function(files) {
let fileArray = [];
let dirArray = [];
// filter out entries that start with .
files = files.filter(function(f) {
return !f.startsWith(".");
});
return Promise.map(files, function(f) {
return fs.statAsync(f).then(function(stats) {
if (stats.isDirectory()) {
dirArray.push(f);
} else {
fileArray.push(f);
}
});
}).then(function() {
// make the resolved value be an object with two properties containing the arrays
return {dirArray, fileArray};
});
});
}
filterFiles().then(function(data) {
res.json(data);
}).catch(function(err) {
// put whatever is appropriate here
res.status(500).end();
});
通過以下更改對它進行了重寫/重組:
.
在處理任何文件之前同步(簡化了異步處理)。 Promise.map()
並行處理值數組。 filterFiles().then()
處理程序中,處理錯誤 res.send()
一個Javascript對象,所以我改用了res.json(data)
(盡管我不確定您真正想要發送的是什么)。 .startsWith()
替換正則表達式比較。 如果您不想使用Bluebird Promise庫,則可以為使用的fs方法創建自己的Promise包裝器,如下所示:
fs.readdirAsync = function(dir) {
return new Promise(function(resolve, reject) {
fs.readdir(dir, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
fs.statAsync = function(f) {
return new Promise(function(resolve, reject) {
fs.stat(f, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
function filterFiles() {
return fs.readdirAsync(rootDir).then(function(files) {
let fileArray = [];
let dirArray = [];
// filter out entries that start with .
files = files.filter(function(f) {
return !f.startsWith(".");
});
return Promise.all(files.map(function(f) {
return fs.statAsync(f).then(function(stats) {
if (stats.isDirectory()) {
dirArray.push(f);
} else {
fileArray.push(f);
}
});
})).then(function() {
// make the resolved value be an object with two properties containing the arrays
return {dirArray, fileArray};
});
});
}
filterFiles().then(function(data) {
res.json(data);
}).catch(function(err) {
res.status(500).end();
});
您遇到的主要問題是沒有解決或拒絕最外部的Promise。 您可以通過解決Promise.all
而不是返回它來解決此問題。
resolve(
Promise.all(actions)
.then(function(resolvedTasks){
// ... next potential issue is here
return {dirArray: dirArray, fileArray: fileArray}
})
);
(我知道,看起來很尷尬吧?)
接下來,在Promise.all解決之后,您的返回值有點奇怪。 在task
函數中,您將項目推送到dirArray
和fileArray
,但是未在代碼段中聲明或分配它們。 我將假定它們在此代碼范圍內。 在這種情況下,您只需要返回所需的對象。
另外,為了使您的異步代碼更具可讀性,以下是一些技巧:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.