Search code examples
node.jsexpressredises6-promise

bluebird coroutine with node redis


I'm trying to use node redis with yield and cannot find a proper way to achieve this.

Basically I want to be able to wait for the promise resolution to make my async code looks like sync code (equivalent to c# yield)

I made a simple test like this but it's not working:

const redisLib = require("redis")
const Promise = require("bluebird")

Promise.promisifyAll(redisLib)

var express = require('express'),
    redis = redisLib.createClient({ host: '127.0.0.1', port: 6379 }),

const redisGetYield = Promise.coroutine(function* (key) {
    const redis = app.get("redis")
    let val = yield redis.getAsync(key)
    return val
})

app.get("/test",function(req,res,next)
{
    let val = redisGetYield("test")
    return res.json({'val':val}).end()
})

The displayed output in my browser is :

{"val":{"isFulfilled":false,"isRejected":false}}

Looks like the yield has no effect, the code don't wait for the resolution of the promise.

I know I can use co-redis , but I want to make this with with node redis for compatibility reasons.


Solution

  • Here is a solution that uses Node 8's promisify. With it, you would not need bluebird coroutine:

    const Promise = require("bluebird")
    const redis = Promise.promisifyAll(require('redis'))
    const express = require('express'),
    
    let client = redis.createClient({ 
      host: '127.0.0.1', port: 6379 
    }));
    
    app.get('/test', async (req, res, next) => {
        let val = await client.get('test');
        return res.json({ val }).end();
    });
    

    Async/await is an extremely powerful JavaScript feature. And with it, I find myself rarely using promises explicitly.

    Note: In a production app, make sure to surround all async calls in a try catch block to catch rejected promises.

    Note 2: I misspoke above. You will still need to use promisifyAll in bluebird. Node 8 has a promisify function, but I forgot that it only works on a single function at a time.