كيفية استخدام الوعود والانتظار مع وظائف Node.js المستندة إلى رد الاتصال

تم إنشاء معظم واجهات برمجة تطبيقات Node.js في وقت لم تكن فيه الوعود شيئًا بعد ، ويستخدمون حلًا قائمًا على رد الاتصال.

تعمل واجهة برمجة تطبيقات Node.js النموذجية على النحو التالي:

doSomething(param, (err, result) => {

})

هذا ينطبق أيضا على المكتبات. مثال واحد هوnode-redis، وأثناء العمل معه في مشروع ما ، في مرحلة ما ، كنت بحاجة إلى إزالة جميع عمليات الاسترجاعات ، لأن لدي مستويات كثيرة جدًا من عمليات الاسترجاعات متداخلة في بعضها البعض - وهو سيناريو مثالي "لرد الاتصال".

أيضًا ، في بعض الأحيان يكون من الضروري للغاية تجنب عمليات الاسترجاعات لأنك تحتاج إلى العودة من الوظيفة إلى نتيجة استدعاء الوظيفة. إذا تم إرجاع ذلك في رد اتصال ، فإن الطريقة الوحيدة لاستعادة النتيجة هي إرسالها مرة أخرى مع وظيفة ، ويستمر فريق رد الاتصال:

const myFunction = () => {
  doSomething(param, (err, result) => {
    return result //can't return this from `myFunction`
  })
}
const myFunction = callback => {
  doSomething(param, (err, result) => {
    callback(result) //no
  })
}

myFunction(result => { console.log(result) })

هناك حل سهل.

حل مقدم من Node.js نفسها.

يمكننا "التعهد" بأي وظيفة لا تدعم الوعود (ونتيجة لذلك ، بناء الجملة غير المتزامن / انتظار) عن طريق استيرادpromisifyمن جوهر Node.jsutilوحدة:

const { promisify } = require('util')

ثم نقوم بإنشاء وظائف جديدة باستخدامه:

const ahget = promisify(client.hget).bind(client)
const asmembers = promisify(client.smembers).bind(client)
const ahkeys = promisify(client.hkeys).bind(client)

انظر كيف أضفتaحرف يعنيغير متزامن.

الآن يمكننا تغيير هذا المثال "callback hell":

client.hget(`user:${req.session.userid}`, 'username', (err, currentUserName) => {
  client.smembers(`followers:${currentUserName}`, (err, followers) => {
    client.hkeys('users', (err, users) => {
      res.render('dashboard', {
        users: users.filter((user) => user !== currentUserName && followers.indexOf(user) === -1)
      })
    })
  })
})

إلى منظف كثيرًا:

const currentUserName = await ahget(`user:${req.session.userid}`, 'username')
const followers = await asmembers(`followers:${currentUserName}`)    
const users = await ahkeys('users')

res.render(‘dashboard’, { users: users.filter((user) => user !== currentUserName && followers.indexOf(user) === -1) })

هذا هو الأمثل عند استخدام وظيفة لا يمكنك الوصول إليها ، كما هو الحال في هذه الحالة حيث أستخدم مكتبة تابعة لجهة خارجية.

تحت غطاء المحرك ، يلف الوعد الوظيفة بوعد ، ويعيدها.

يمكنك القيام بذلك يدويًا أيضًا ، وإعادة وعد من دالة ، ثم استخدامه مع async / wait:

const handleLogin = (req, user) => {
  return new Promise((resolve, reject) => {
    req.login(user, (err) => {
      if (err) {
        return reject({
          error: true,
          message: err,
        })
      }
      return resolve({
        success: true,
      })
    })
  })
}

//… const resultLogin = await handleLogin(req, user)

تحميل مجانيكتيب Node.js


المزيد من دروس العقدة: