2016-10-18 71 views
2

我有這個功能就在這裏:爲什麼我在Node.js中發生分段錯誤?

function createInsta(email, userid) { 
    if (!fs.existsSync('users/' + email + '/' + userid)) { 
    fs.mkdir('users/' + email + '/' + userid) 
    fs.writeFileSync(('users/' + email + '/' + userid + '/instagram.json'), fs.readFileSync("data/data.json", "utf-8")) 
    console.log("insta folder created"); 
    } 
    console.log("Initializing Data") 
    var data = fs.readFileSync('users/' + email + '/' + userid + '/instagram.json', "utf-8") 
    data = JSON.parse(data); 
    var result; 
    request(("https://instagram.com/" + userid + "/?__a=1"), function(error, response, body) { 
    var res = JSON.parse(body); 
    result = res.user.followed_by.count 
    if (error) { 
     console.log(err) 
    } 
    }) 
    while (result === undefined) { 
    deasync.sleep(100) 
    } 
    data.STARTING_COUNTS[0].DAY = result; 
    data.STARTING_COUNTS[0].WEEK = result; 
    data.STARTING_COUNTS[0].MONTH = result; 

} 

控制檯打印出局Initializing Data之後,控制檯說:Segmentation fault

我不知道這是爲什麼,似乎我的代碼並不像什麼事情都可能造成這樣的一個錯誤。

任何指針?謝謝

+0

「任何指針」 - 雙關語意? – joews

+0

我不喜歡 - >'的外觀while(result === undefined){deasync.sleep(100)}'爲什麼它需要? – Keith

+0

@Keith我用它作爲一個簡單而快速的繞着nodejs這個函數的異步模型,我用它在其他函數中沒有問題,我懷疑它的段錯誤原因 – Vikaton

回答

2

如承諾(赦免雙關語),這裏開始將您的代碼轉換爲承諾/等待。

這是開始使您的代碼使用承諾,有更多的錯誤檢查需要等,但我故意做的代碼現在太少顯示更改,我們可以重構,因爲我們去上。

例如。所有那些fs.existsSync等,都希望成爲承諾,所以我們可以擺脫所有的同步的東西。你的node.js應用程序會喜歡你。

後來我們可以做得更多。 Promise的內置到瀏覽器/節點是好的,但我也發現一個Promise庫可以讓事情變得更容易,我會建議藍鳥 - >http://bluebirdjs.com/docs/getting-started.html它也許值得有一個很好的閱讀,藍鳥有一些有用的實用功能,如promisify,將使你的fs.func更容易。

所以我認爲現在應該做,而且我們稍後會做另一個重構。

//lets mark this function as async.. 
 
async function createInsta(email, userid) { 
 
    return new Promise(function (resolve, reject) { 
 
    if (!fs.existsSync('users/' + email + '/' + userid)) { 
 
     fs.mkdir('users/' + email + '/' + userid) 
 
     fs.writeFileSync(('users/' + email + '/' + userid + '/instagram.json'), fs.readFileSync("data/data.json", "utf-8")) 
 
     console.log("insta folder created"); 
 
    } 
 
    console.log("Initializing Data") 
 
    var data = fs.readFileSync('users/' + email + '/' + userid + '/instagram.json', "utf-8") 
 
    data = JSON.parse(data);  
 
    request(("https://instagram.com/" + userid + "/?__a=1"), function(error, response, body) { 
 
     if (error) { 
 
     console.log(err) 
 
     return reject(error); 
 
     } 
 
     var res = JSON.parse(body); 
 
     var result = res.user.followed_by.count 
 
     data.STARTING_COUNTS[0].DAY = result; 
 
     data.STARTING_COUNTS[0].WEEK = result; 
 
     data.STARTING_COUNTS[0].MONTH = result; 
 
     resolve(data); //i'm assuming data is what your wanting to return 
 
    }) 
 
    }); 
 
} 
 

 
//to be able to use await our function also needs to be async 
 
async function run() { 
 
var data = await createInsta('[email protected]'); 
 
}

+0

謝謝!我在閱讀這本書之前確實看過藍鳥,並將我的回調代碼重構爲承諾:https://gist.github.com/Vikaton/18cf0891e8c00ff2d7cbfdbfdca83e26但是,您的代碼看起來更加簡潔,您的代碼是否比promisified更好? – Vikaton

+0

Promisified,僅僅是Bluebird用來將節點回調轉換爲基於Promise的功能的一個術語。我添加了一個新帖子,顯示了這一點。 – Keith

1

好吧,讓我們重構過去後。

我們使用new Promise()構造函數的原因只有一個,那是因爲請求是異步。事實上,我犯了一個小錯誤,因爲一些錯誤不會以正確的方式處理。我應該做的是將new Promise()移到請求前。

Promise的一個好處是,錯誤會傳播到鏈中,在我們的例子中,我們的請求對象中有一個console.log()。有什麼更好的是,所有未處理的錯誤都在一個地方處理。在這個例子中,run()函數似乎是一個不錯的地方。

如果你現在看看你的createInsta函數,你會認爲它使用了所有的同步函數,但實際上除了existsSync之外,其他的一切都是異步的。就像在評論中提到的那樣,existSync真的想要刪除。相反,只需創建目錄並在try catch中捕獲錯誤,或者甚至更好地創建一個名爲tryMkDir的實用程序函數,這樣做(當然是承諾).. :)

最後一個註釋,await/async是一個相當新的JavaScript,我認爲它是ES7,我不相信它甚至還沒有最終確定。但是你現在可以使用它,比如使用Babel。

//lets make a Promise based request. 
 
//There is an NPM module that would do this and more 
 
//but this is a good example of making existing callback 
 
//functions into a Promise. 
 

 
async function promRequest(url) { 
 
    return new Promise(function(resolve, reject) { 
 
    request(url, function(error, response, body) { 
 
     if (error) return reject(error); 
 
     //promises can only return one thing 
 
     //so use an object literal to return more 
 
     resolve({ 
 
     response:response, 
 
     body: body 
 
     }); 
 
    }); 
 
    }); 
 
} 
 

 
//lets also promisify some Node stuff. 
 
var Promise = require('bluebird'); 
 

 
//there is a promisifyall, but I like to be 
 
//specific about what I promisify. 
 
var fsWriteFile = Promise.promisify(fs.writeFile), 
 
    fsReadFile = Promise.promisify(fs.readFile), 
 
    fsMkdir = Promise.promisify(fs.mkdir); 
 

 

 
//because promRequest is already a promise 
 
//we can now get rid of the new Promise contructor here. 
 
//The only part of this function that is now async 
 
//is existsSync, the exists() in node is depreciated 
 
//due to potential race conditions, really this 
 
//should be altered to just try and create dirctory 
 
//and catch error if exists. 
 
async function createInsta(email, userid) { 
 
    if (!fs.existsSync('users/' + email + '/' + userid)) { 
 
    await fsMkdir('users/' + email + '/' + userid); 
 
    await fsWriteFile(('users/' + email + '/' + userid + '/instagram.json'), await fsReadFile("data/data.json", "utf-8")); 
 
    console.log("insta folder created"); 
 
    } 
 
    console.log("Initializing Data") 
 
    var data = await fsReadFile('users/' + email + '/' + userid + '/instagram.json', "utf-8") 
 
    data = JSON.parse(data);  
 
    var res = JSON.parse(
 
    await promRequest("https://instagram.com/" + userid + "/?__a=1").body); 
 
    var result = res.user.followed_by.count 
 
    data.STARTING_COUNTS[0].DAY = result; 
 
    data.STARTING_COUNTS[0].WEEK = result; 
 
    data.STARTING_COUNTS[0].MONTH = result; 
 
    return data; 
 
} 
 

 
//to be able to use await our function also needs to be async 
 
async function run() { 
 
    //lets catch all unahandled errors here. 
 
    try { 
 
    var data = await createInsta('[email protected]'); 
 
    } catch (e) { 
 
    //fantasic any error's can now be logged 
 
    //eg. fsMkdir might have failed and it's still 
 
    //going to be logged here.. 
 
    console.log(e); 
 
    } 
 
}

+0

非常感謝你! – Vikaton

相關問題