简体   繁体   English

如何使功能与等待同时还可以进行回调?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM