如何使用等待的函数,也可以进行回调?

时间:2017-09-24 01:06:17

标签: javascript ecmascript-6

我想创建一个可以同时使用async / await和通常的回调模式的函数。所以像下面这样的东西会起作用:

get_dict

但是下面的内容不会起作用

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需要返回一个承诺,尽管我对如何采取回调和回报承诺的想法很少,但我还是喜欢看到一些正确的方法来做到这一点。

3 个答案:

答案 0 :(得分:3)

你可以像这样使用

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

答案 1 :(得分: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}`)
})

上述实现在使用回调调用时故意不返回promise。如果你它这样做,那么我推荐这种方法,因为它更灵活一点(即如果你想传递一个回调并仍然把它视为当时的能力):

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}`)
})

答案 2 :(得分: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)
})