2016-09-21 40 views
1

我目前正在使用一個將被集成到用戶自己的Web服務器中的API /路由器。我的代碼將完成所需的工作,但也允許用戶在之後實現自己的邏輯,例如以下片段:myApi.on('action', (err, result, req, res) => {/*user's logic here*/})如何promisify一個不包含回調參數的函數?

按照設計,如果用戶決定重寫默認行爲並實現自己的邏輯,我的代碼將不會結束響應。這是爲了允許請求和響應在用戶需要時進入下一個中間件功能。

我想要的控制流程是:

  1. 運行我的初始路徑邏輯

  2. 運行用戶的自定義邏輯

  3. 控制傳遞給下一個中間件的功能,如果反應還沒有已結束

我的問題出現時用戶想要實現任何異步邏輯。在將控制權交給下一個中間件功能之前,我無法讓用戶的自定義邏輯結束。我相信這是因爲我設置的界面。我希望用戶儘可能做一些小工作。這意味着我不希望向用戶傳遞一些他們需要在其邏輯的每個端點上調用的功能(因爲我的路由器涉及許多不同的路由),因此不需要傳遞相應的功能callback()next()

我已經看過承諾包裝如promisify-node,但他們似乎只能包裝函數,將回調作爲他們的最終參數。我也考慮要求用戶從自定義實現中返回一個承諾,但這違背了我不希望繁忙/樣板代碼的願望。

有什麼方法可以使用承諾 - 或任何其他構造 - 我可以處理這個異步問題,而不必痛苦用戶?

+0

如何定義請求結束? – Amit

+0

@Amit,似乎我切換了請求和響應。我會通過檢查res.finished標籤來檢查**響應**是否完成。 – TheKingOfTyrants

回答

1

不,你不能promisify一個函數,不採取回調。這樣的功能或者不是異步的,或者不能讓你知道什麼時候完成 - 你運氣不好。

我的問題出現在用戶想要實現任何異步邏輯時。

只需要用戶傳遞一個函數來返回一個承諾,如果他想實現異步的東西。它可能會做的他也不得不與承諾的工作:-)

const myApi = { 
    on(name, fn) { 
     Promise.resolve(result) // or whenever you need to run the user logic 
     .then(result => 
      fn(req, result) // or whatever you want to pass 
     ) 
     .then(customresult => { 
      res.write(customresult); // or whatever you want to do with its result 
     }); 
    } 
}; 

myApi.on('action', (req, result) => { 
    // user's logic here 
    // throw exceptions 
    // return values 
    // return promises for values 
    // or whatever the user needs to do 
}) 
0

如果我知道你會檢查值的用戶自定義函數返回問題的青睞。如果它是一個承諾,如對象,那麼你可以等待它解決之後繼續前進。這相當於將next函數傳遞給用戶的自定義中間件。

在您的例子中,用戶(S)將使用自己的API,像這樣:

myApi.on('action', (err, result, req, res) => { 
    return myPromiseAwareAsyncFunction(); 
}) 

並在代碼:

let userMiddleWare = lookupNextActionHandler(); 
let result = userMiddleWare(err, result, req, res); 
// Wrap any value (promise or not) in a promise 
Promise.resolve(result) 
    .then(result => { 
    // Move on to next middle ware 
    }) 
    .catch(error => { 
    console.error(error); 
    process.exit(1); // Or what ever you use 
        // to end the middle ware chain. 
    }); 

如果你想同時提供承諾一個next回調你可以這樣做:

let userMiddleWare = lookupNextActionHandler(); 
new Promise((resolve, reject) => { 
    function next(err) { 
    if (err) { 
     reject(err); 
    } else { 
     resolve(); 
    } 
    } 
    let result = userMiddleWare(err, result, req, res, next); 
    Promise.resolve(result).then(resolve).catch(reject); 
}) 
.then(result => { 
    // Move on to next middle ware 
}) 
.catch(error => { 
    console.error(error); 
    process.exit(1); // Or what ever you use 
        // to end the middle ware chain. 
}); 

由於承諾只能處理一個解決方案,並且在設置後會忽略更多咒語,這將會起作用,並且用戶使用哪個(next或返回承諾)將起作用。

相關問題