2016-10-10 53 views
0

我想在通過一些條件解決後停止承諾鏈。下面的代碼可能有助於理解我在說什麼。如何在解決後停止承諾鏈?

function update(id, data) { 
    return new Promise((resolve, reject) => { 
     let conn; 

     pool.get() 
     .then((db) => { 
      conn = db; 

      if(Object.keys(data).length === 0) { 
       return resolve({ updated: 0 }); 
      } 
      else { 
       return generateHash(data.password); 
      } 
     }) 
     .then((hash) => { 
      conn.query("UPDATE ... ", (err, queryResult) => { 
       if(err) { 
        throw err; 
       } 

       resolve({ updated: queryResult.affectedRows }); 
      }); 
     }) 
     .catch((err) => { ... }) 
    }); 
} 

請注意,pool.get()是承諾封裝的API,用於從我製作的MySQL模塊獲取連接池。

我想要做的是更新用戶數據。並且爲了節省服務器資源,如果沒有要更新的數據(Object.keys(data).length === 0),我會避免更新。

當我嘗試這個代碼時,第二(更新數據庫)總是發生,即使沒有數據更新!

我讀this post,但它沒有奏效。爲什麼在我稱之爲「return resolve();」時承諾鏈沒有停止?如何正確地阻止它?我真的很喜歡使用承諾,但有時候,這種事情讓我發瘋。這將是非常感謝,幫助我解決這個問題。謝謝!

P.S.無論如何,我使用node v6.2.2。

+0

首先,您使用的是無極構造反模式。其次,RESOLV在鏈條的一部分中保證可以進入下一個鏈接 - 這就是鏈條如何工作的原因! –

+0

你可以在這裏接受幫助http://stackoverflow.com/questions/20714460/break-promise-chain-and-call-a-function-based-on-the-step-in-the-chain-where-it – abdulbarik

+0

爲什麼在檢查傳入的'data'是否沒有密鑰之前,你需要等到**你'pool.get'之後的**? –

回答

4

爲什麼當我所謂的「迴歸的決心();」無極鏈未停止?

您已經從當前的then回調並履行了外部承諾。但是這並沒有「停止」任何東西,然後then鏈仍然會繼續通過回調的返回值來解析。

如何正確地阻止它?

您需要put the then call inside the if到具備條件適用於它:

pool.get() 
.then((db) => { 
    … 
    if (Object.keys(data).length === 0) { 
     …({ updated: 0 }); 
    } else { 
     return generateHash(data.password) 
     .then((hash) => { 
      conn.query("UPDATE ... ", (err, queryResult) => { 
       … 
      }); 
     }) 
    } 
}) 
.catch((err) => { ... }) 

在任何情況下,你應該避免Promise constructor antipattern!您應該只promisifyquery方法:

function query(conn, cmd) { 
    return new Promise((resolve, reject) => { 
     conn.query(cmd, (err, queryResult) => { 
      if (err) reject(err); // Don't throw! 
      else resolve(queryResult); 
     }); 
    }); 
} 

,然後使用:

function update(id, data) { 
    return pool.get() 
    .then(conn => { 
     if (Object.keys(data).length === 0) { 
      conn.close(); // ??? 
      return { updated: 0 }; 
     } else { 
      return generateHash(data.password) 
      .then(hash => { 
       return query(conn, "UPDATE ... ") 
      }).then(queryResult => { 
       conn.close(); // ??? 
       return { updated: queryResult.affectedRows }; 
      }, err => { 
       … 
       conn.close(); // ??? 
      }); 
     } 
    }); 
} 

請注意,它可能沒有什麼意義得到來自池的連接,如果你能事先知道,沒有查詢會製成,所以也許你應該把if在頂層:

function update(id, data) { 
    if (Object.keys(data).length === 0) { 
     return Promise.resolve({ updated: 0 }); 
    } else { 
     return pool.get() 
     .then(conn => { 
      return generateHash(data.password) 
      .then(hash => { 
       return query(conn, "UPDATE ... ") 
      }).then(queryResult => { 
       conn.close(); // ??? 
       return { updated: queryResult.affectedRows }; 
      }, err => { 
       … 
       conn.close(); // ??? 
      }); 
     }); 
    } 
} 
+0

hmmm'return解決({更新:0});'... Promise.resolve也許? –

+0

@JaromandaX不知道,這是非清理版本,我只專注於'if' /'then'嵌套 – Bergi

+0

你錯過了= > in'conn.query(cmd,(err,queryResult)=> {' –

0

這將是使用if聲明的良好局面:

function update(id, data) { 
    if (Object.keys(data).length === 0) { 
     return Promise.resolve({ updated: 0 }); 
    } 

    let conn; 

    return pool.get() 
     .then((db) => { 
      conn = db; 

      return generateHash(data.password); 
     }) 
     .then((hash) => { 
      return new Promise(function (resolve, reject) { 
       conn.query("UPDATE ... ", (err, queryResult) => { 
        if(err) { 
         reject(err); 
        } 

        resolve({ updated: queryResult.affectedRows }); 
       }); 
      }); 
     }) 
     .catch((err) => { ... }) 
} 
+1

用'Promise.resolve'和'$ q替換'$ q.when'。 。'with'new Promise(...' - 因爲沒有跡象表明這個'$ q'庫被用於 –

+0

@JaromandaX這個問題謝謝。由於某種原因,我認爲這是一個有問題的問題。 – JLRishe