亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

函數運行后數組為空?

函數運行后數組為空?

UYOU 2023-04-27 16:14:10
app.post('/api/edit-profile', regularFunctions, async function (req, res) {    let email = req.body.email    let password_current = req.body.password_current    connection.query('SELECT * FROM accounts WHERE id = ?', req.body.id, async function (err, results) {        if (results.length > 0) {            bcrypt.compare(password_current, results[0].password, async function (err, isMatch) {                if (err) {                    res.send('Unable to save settings')                    res.end();                    throw err                } else if (!isMatch) {                    res.send('Password doesn\'t match.')                    res.end();                } else {                    let changed = []                    // Password matches                    if (req.body.password_new) {                        let newPassword = req.body.password_new                        let hashed_password = await hashPassword(newPassword)                        connection.query('UPDATE accounts SET password = ? WHERE id = ?', [hashed_password, req.body.id], async function (error, results) {                            if (results.affectedRows && results.affectedRows > 0) {                                changed.push('password')                            } else {                                res.send('Unable to save settings')                                res.end();                            }                        })                    }我知道這對一些專家編碼員來說似乎是一個非常簡單的問題,但我對整個異步和同步的事情有點陌生。為什么“已更改”數組即使在函數運行后被推送到也不會更新?我想做的是讓它只返回一個可以在客戶端顯示的字符串,但它似乎并沒有改變它,只返回“成功改變,”
查看完整描述

2 回答

?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

這個功能讓我感到困惑,因為它有很多責任,但我發現了問題:

connection.query方法是非阻塞的,這意味著它不會等待它的執行結束以前進到下一條指令。

當您使用異步方法和時Promise,最好嘗試保持方法的一致性(避免混合回調函數和async/?await)。async如果使用/ ,我已經重構了它應該是什么樣子await

app.post('/api/edit-profile', regularFunctions, async function (req, res) {

? ? let email = req.body.email

? ? let password_current = req.body.password_current

? ? let results = await executeQuery(connection, 'SELECT * FROM accounts WHERE id = ?', [req.body.id]);

? ? if (results.length > 0) {

? ? ? ? let isMatch = await comparePassword(password_current, results[0].password);

? ? ? ? if (!isMatch) {

? ? ? ? ? ? throw new Error(`Password doesn't match`);

? ? ? ? }

? ? ? ? let changed = []

? ? ? ? // Password matches

? ? ? ? if (req.body.password_new) {

? ? ? ? ? ? let newPassword = req.body.password_new

? ? ? ? ? ? let hashed_password = await hashPassword(newPassword)

? ? ? ? ? ? let results = await executeQuery(connection, 'UPDATE accounts SET password = ? WHERE id = ?', [hashed_password, req.body.id]);

? ? ? ? ? ? if (results.affectedRows && results.affectedRows > 0) {

? ? ? ? ? ? ? ? changed.push('password')

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? throw new Error('Unable to save settings');

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? if (req.body.license_key) {

? ? ? ? ? ? let newKey = req.body.license_key

? ? ? ? ? ? let response = await axios.get(`https://voltcloud.net/api/hosting/check-key/${newKey}`, {

? ? ? ? ? ? ? ? headers: {

? ? ? ? ? ? ? ? ? ? authorization: '<redacted>'

? ? ? ? ? ? ? ? }

? ? ? ? ? ? });

? ? ? ? ? ? let data = response.data

? ? ? ? ? ? if (typeof data === 'object') {

? ? ? ? ? ? ? ? if (data.active === 1) {

? ? ? ? ? ? ? ? ? ? let response = await axios({

? ? ? ? ? ? ? ? ? ? ? ? method: 'post',

? ? ? ? ? ? ? ? ? ? ? ? url: `https://voltcloud.net/api/hosting/activate-key/${newKey}`,

? ? ? ? ? ? ? ? ? ? ? ? headers: {

? ? ? ? ? ? ? ? ? ? ? ? ? ? authorization: '<redacted>'

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? })

? ? ? ? ? ? ? ? ? ? if (response.data === 'Success') {

? ? ? ? ? ? ? ? ? ? ? ? let results = await executeQuery(connection, 'UPDATE accounts SET license_key = ? WHERE id = ?', [newKey, req.body.id]);

? ? ? ? ? ? ? ? ? ? ? ? if (results.affectedRows && results.affectedRows > 0) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? changed.push('license key')

? ? ? ? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ? ? ? throw new Error('Unable to save settings');

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? } else if (data === 'License already active!') {

? ? ? ? ? ? ? ? ? ? ? ? throw new Error('License key is already active!');

? ? ? ? ? ? ? ? ? ? } else if (data === 'Failed to update key.') {

? ? ? ? ? ? ? ? ? ? ? ? throw new Error('Unable to save settings');

? ? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ? throw new Error('Unable to save settings');

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? let results = await executeQuery(connection, 'UPDATE accounts SET email = ? WHERE id = ?', [email,req.body.id]);

? ? ? ? if (results.affectedRows && results.affectedRows > 0) {

? ? ? ? ? ? changed.push('email')

? ? ? ? } else {

? ? ? ? ? ? throw new Error('Unable to save settings');

? ? ? ? }

? ? ? ? let finalTxt = 'Successfully changed, '

? ? ? ? if (changed.length > 1) {

? ? ? ? ? ? changed.forEach(function (txt, index) {

? ? ? ? ? ? ? ? if (index === 0) {

? ? ? ? ? ? ? ? ? ? finalTxt = finalTxt + txt

? ? ? ? ? ? ? ? } else if (index === 2) {

? ? ? ? ? ? ? ? ? ? finalTxt = finalTxt + `and ${txt}.`

? ? ? ? ? ? ? ? }

? ? ? ? ? ? })

? ? ? ? } else if (changed.length === 1) {

? ? ? ? ? ? finalTxt = `Successfully changed ${changed[0]}.`

? ? ? ? }

? ? ? ? res.send(finalTxt)

? ? ? ? res.end();

? ? }

});


function executeQuery(conn, sql, params) {

? ? return new Promise((resolve, reject) => {

? ? ? ? conn.query(sql, params, function (err, data) {

? ? ? ? ? ? if (err != null) {

? ? ? ? ? ? ? ? return reject(err);

? ? ? ? ? ? }

? ? ? ? ? ? return resolve(data);

? ? ? ? });

? ? });

}


function comparePassword(val1, val2) {

? ? return new Promise((resolve, reject) => {

? ? ? ? bcrypt.compare(val1, val2, function (err, isMatch) {

? ? ? ? ? ? if (err != null) {

? ? ? ? ? ? ? ? return reject(err);

? ? ? ? ? ? }

? ? ? ? ? ? resolve(isMatch);

? ? ? ? });

? ? })

}

請注意,我們根本沒有使用回調函數,即使在我們沒有基于本機的Promise函數(即 mysql 連接)的情況下,我們也委托給一個函數來代理回調以提供Promise并保持最終的一致性執行。


查看完整回答
反對 回復 2023-04-27
?
喵喵時光機

TA貢獻1846條經驗 獲得超7個贊

if原始代碼在發送響應之前并沒有等待兩個分支完成。由于嵌套,很難在回調中構造這樣的代碼。

盡可能使用async函數await。它允許更多的可讀代碼和更容易的錯誤處理。所以這個答案更多的是代碼審查,而不是針對您的問題的簡單修復。

拆分出一些在其他路由中有用的通用幫助代碼:

// Generate errors for the web, with context

function responseError(message, status, data){

? ? const error = new Error(message)

? ? error.status = status

? ? for (const key in data){

? ? ? ? error[key] = data[key]

? ? }

? ? return error

}


// Turn mysql callbacks into promises (or use util.promisify)

async function runQuery(query, values){

? ? return new Promise((resolve, reject) => {

? ? ? ? connection.query(query, values, function(error, results){

? ? ? ? ? ? if (error) return reject(error)

? ? ? ? ? ? return resolve(results)

? ? ? ? })

? ? })

}


async function runUpdateQuery(query, values){

? ? const results = await runQuery(query, values)

? ? if (!results) throw responseError('No update result', 500, { query })

? ? if (!results.affectedRows) throw responseError('No affected rows', 400, { query })

? ? return results

}

來自兩個條件的代碼if可以很容易地分開,以及其他帳戶操作。


async function apiAuthUserId(id, password){

? ? const results = await runQuery('SELECT * FROM accounts WHERE id = ?', id)

? ? if (!results.length) throw responseError('No account', 400, { id })

? ? const isMatch = await bcrypt.compare(password_current, results[0].password)

? ? if (!isMatch) throw responseError('Password doesn\'t match', 400)

? ? return true

}


async function apiUpdatePassword(id, password){

? ? let newPassword = req.body.password_new

? ? let hashed_password = await hashPassword(newPassword)

? ? await runUpdateQuery('UPDATE accounts SET password = ? WHERE id = ?', [hashed_password, req.body.id])

? ? return id

}


async function apiUpdateEmail(id, email){

? ? await runUpdateQuery('UPDATE accounts SET email = ? WHERE id = ?', [email, id])

? ? return email

}


async function apiUpdateLicenseKey(id, licenseKey){

? ? const response_license = await axios.get(`https://voltcloud.net/api/hosting/check-key/${licenseKey}`, {

? ? ? ? headers: {

? ? ? ? ? ? authorization: 'somekey'

? ? ? ? }

? ? })


? ? const data = response_license.data

? ? if (!data) {

? ? ? throw responseError('No license key response data', 500, { response: response_license })

? ? }

? ? if (data.active !== 1) {

? ? ? throw responseError('License key not active', 400,? { key: licenseKey })

? ? }

? ? const response_activate = await axios({

? ? ? ? method: 'post',

? ? ? ? url: `https://voltcloud.net/api/hosting/activate-key/${licenseKey}`,

? ? ? ? headers: {

? ? ? ? ? ? authorization: 'somekey'

? ? ? ? }

? ? })


? ? switch (response_activate.data){

? ? ? ? case 'License already active!':

? ? ? ? ? ? throw responseError('License key is already active!', 400, { response: response_activate })

? ? ? ? case 'Failed to update key.':

? ? ? ? ? ? throw responseError('Unable to save settings!', 400, { response: response_activate })

? ? ? ? case 'Success':

? ? ? ? ? ? await runUpdateQuery('UPDATE accounts SET license_key = ? WHERE id = ?', [licenseKey, req.body.id])

? ? ? ? ? ? return licenseKey

? ? ? ? default:

? ? ? ? ? ? throw responseError('Unable to save settings!', 500, { response: response_activate })

? ? }

}

這樣您的路由代碼就可以更簡潔一些,并顯示需要完成的工作,而不是如何完成所有工作。


app.post('/api/edit-profile', regularFunctions, async function (req, res) {

? ? const changed = []

? ? try {

? ? ? ? const { id, email, password_current } = req.body


? ? ? ? await apiAuthUserId(id, password_current)


? ? ? ? // Password matches

? ? ? ? if (req.body.password_new) {

? ? ? ? ? ? await apiUpdatePassword(id, req.body.password_new)

? ? ? ? ? ? changed.push('password')

? ? ? ? }


? ? ? ? // License key

? ? ? ? if (req.body.license_key) {

? ? ? ? ? ? await apiUpdateLicenseKey(id, req.body.license_key)

? ? ? ? ? ? changed.push('license key')

? ? ? ? }


? ? ? ? await apiUpdateEmail(id, email)

? ? ? ? changed.push('email')


? ? ? ? let finalTxt = `Successfully changed ${changed.join(' and ')}.`

? ? ? ? res.send(finalTxt)

? ? }

? ? catch (error) {

? ? ? ? // If your not using transactions, might need to deal with partial `changed` responses here.?

? ? ? ? console.error('Error /api/edit-profile', error)

? ? ? ? res.status(error.status||500).send(`Error: ${error.message}`)

? ? }

});


查看完整回答
反對 回復 2023-04-27
  • 2 回答
  • 0 關注
  • 140 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號