[英]How to make function that works with await but also can take callback?
I want to create a function that can work with both async/await and usual callback pattern. 我想创建一个可以与异步/等待和通常的回调模式一起使用的函数。 so something like the following would work: 因此,以下内容将起作用:
function myFunc(cb) {
setTimeout(function(){ //something async
console.log('hello');
cb();
});
}
myFunc(function(){
console.log('world');
});
but what is below won't work 但是下面的内容不起作用
function myFunc(cb = function(){}) {
setTimeout(function(){ //something async
console.log('hello');
cb();
}, 1000);
}
(async ()=> {
await myFunc();
console.log('world');
})();
I understand for await
to work myFunc
needs to return a promise and even though i've few ideas in mind on how to take callback and return promise, I'd like to see some proper way to do this. 我知道await
工作myFunc
需要返回一个承诺,即使我对如何进行回调和返回承诺的想法不多,我还是希望看到一些正确的方法来做到这一点。
You can use both like this 您可以像这样同时使用
function myFunc (giveback, callback) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(giveback);
if (typeof callback === 'function') callback(null, giveback);
}, 1000)
}
}
Typically, the way to achieve this is to check the amount of arguments explicitly passed, and act accordingly. 通常,实现此目的的方法是检查显式传递的参数数量,并采取相应措施。
If you want myFunc()
to achieve both styles simultaneously, here's a possible implementation: 如果希望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}`) })
The above implementation intentionally does not return a promise when invoked with a callback. 上面的实现在通过回调调用时有意不返回promise。 If you want it to do so, then I recommend this approach, as it's a little more flexible (ie if you want to pass a callback and still treat it as a then-able): 如果您希望这样做,那么我建议您采用这种方法,因为它稍微灵活一些(即,如果您想传递一个回调并将其仍然视为可行的话):
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}`) })
Here is a functional example of what I described earlier: 这是我先前描述的功能示例:
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)
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.