2017-09-24 28 views
1

我想創建一個可以同時處理異步/等待和常用回調模式的函數。所以像下面將工作:如何使功能與await一起工作,但也可以採取回調?

function myFunc(cb) { 
    setTimeout(function(){ //something async 
     console.log('hello'); 
     cb(); 
    }); 
} 

myFunc(function(){ 
    console.log('world'); 
}); 

,但下面是什麼都不行

function myFunc(cb = function(){}) { 
    setTimeout(function(){ //something async 
     console.log('hello'); 
     cb(); 
    }, 1000); 
} 

(async()=> { 
    await myFunc(); 
    console.log('world'); 
})(); 

我理解await工作myFunc需要返回一個承諾,即使我一些想法考慮如何回調和回覆承諾,我希望看到一些正確的方法來做到這一點。

+2

通常,當我看到這在庫中,函數採用2個參數與所述第二個是回調,如果該參數是omitte d,它會返回一個承諾。 – agm1984

回答

3

你可以這樣

function myFunc (giveback, callback) { 
    return new Promise((resolve, reject) => { 
     setTimeout(function() { 
      resolve(giveback); 
      if (typeof callback === 'function') callback(null, giveback); 
     }, 1000) 
    } 
} 
+0

由於'callback'可能導致運行時錯誤無法傳遞。 I.e'Uncaught TypeError:undefined不是函數'。 – Svenskunganka

2

通常使用兩種,實現這一目標的方法是檢查的明確傳遞的參數量,並採取相應的行動。

如果你想myFunc()同時實現這兩種風格,這裏有一個可能的實現:

function myFunc(cb) { 
 
    // some async logic 
 
    const p = new Promise((resolve, reject) => { 
 
    setTimeout(() => { 
 
     // pass some value here 
 
     resolve('success') 
 
    }, 1000) 
 

 
    setTimeout(() => { 
 
     // pass some error here 
 
     reject(new Error('something broke')) 
 
    }, Math.random() * 2000) // 50% chance of failure 
 
    }) 
 

 
    if (arguments.length < 1) { 
 
    // invoked promise-style 
 
    return p 
 
    } else if (typeof cb === 'function') { 
 
    // invoked callback-style with valid function 
 
    p.then(result => { cb(null, result) }, error => { cb(error) }) 
 
    } else { 
 
    // invoking in callback-style with a non-function 
 
    // should produce a fatal error 
 
    throw new TypeError('cb is not a function') 
 
    } 
 
} 
 

 
// usage 
 

 
try { 
 
    // invalid invocation without function parameter 
 
    myFunc('strings do not implement [[Call]]') 
 
} catch (error) { 
 
    console.log(error.message) 
 
} 
 

 
// callback-style 
 
myFunc((error, value) => { 
 
    if (error) return console.log(`callback with error: ${error.message}`) 
 
    console.log(`callback with value: ${value}`) 
 
}) 
 

 
// promise-style 
 
myFunc().then(value => { 
 
    console.log(`promise with value: ${value}`) 
 
}, error => { 
 
    console.log(`promise with error: ${error.message}`) 
 
})

上述實施時調用的回調故意不返回的承諾。如果您它這樣做的話,我推薦這種方法,因爲它(如果你想傳遞一個回調,仍然把它作爲一個當時能IE)是一個更靈活一點:

function myFunc(cb =() => {}) { 
 
    if (arguments.length > 0 && typeof cb !== 'function') { 
 
    // invoking in callback-style with a non-function 
 
    // should produce a fatal error 
 
    throw new TypeError('cb is not a function') 
 
    } 
 

 
    // some async logic 
 
    return new Promise((resolve, reject) => { 
 
    setTimeout(() => { 
 
     // pass some value here 
 
     resolve('success') 
 
    }, 1000) 
 

 
    setTimeout(() => { 
 
     // pass some error here 
 
     reject(new Error('something broke')) 
 
    }, Math.random() * 2000) // 50% chance of failure 
 
    }).then(result => { 
 
    cb(null, result) 
 
    // propagate result 
 
    return result 
 
    }, error => { 
 
    cb(error) 
 
    // propagate error 
 
    throw error 
 
    }) 
 
} 
 

 
// usage 
 

 
try { 
 
    // invalid invocation without function parameter 
 
    myFunc('strings do not implement [[Call]]') 
 
} catch (error) { 
 
    console.log(error.message) 
 
} 
 

 
// callback-style 
 
myFunc((error, value) => { 
 
    if (error) return console.log(`callback with error: ${error.message}`) 
 
    console.log(`callback with value: ${value}`) 
 
}) 
 

 
// promise-style 
 
myFunc().then(value => { 
 
    console.log(`promise with value: ${value}`) 
 
}, error => { 
 
    console.log(`promise with error: ${error.message}`) 
 
}) 
 

 
// using both styles 
 
myFunc((error, value) => { 
 
    if (error) return console.log(`mixed callback with error: ${error.message}`) 
 
    console.log(`mixed callback with value: ${value}`) 
 
}).then(value => { 
 
    console.log(`mixed promise with value: ${value}`) 
 
}, error => { 
 
    console.log(`mixed promise with error: ${error.message}`) 
 
})

1

這裏是我所描述的功能例更早:

const myFunc = (obj, callback) => { 
    if (!callback) { 
     const performWork = async() => obj 
     return new Promise(async (resolve, reject) => { 
      const value = await performWork() 
      resolve(value) 
     }) 
    } 
    const cb = obj 
    callback(cb) 
} 

const test = { test: 1337 } 

// Promise version 
myFunc(test) 
    .then((res) => console.log('Promise version', res)) 

// Callback version 
myFunc(test, (res) => { 
    console.log('Callback version', res) 
}) 
相關問題