使用fs.writeFileSync时避免竞争条件

时间:2018-02-12 13:23:09

标签: javascript node.js

我正在使用bluebird,request-promise和writeFileSync来下载png并将其写入文件,我的代码是:`

function downloadPng(url) {
    return new Promise(function (resolve, reject) {
        return request.get({
            url : url,
            headers : header,
            encoding: 'binary',
        }).then((res) => {
            fs.writeFileSync('fileName', res, 'binary')
            return foo('fileName')//my function using fileName
        }).then((resultFromFoo) => {
            resolve(resultFromFoo)        
        }).catch((error) => {
            reject(error)
        })

我认为使用writeFileSync确保foo只会在writeFileSync成功后执行?但我仍然得到一个竞争条件,我的foo在文件创建之前调用,我是如何正确地做到的?

1 个答案:

答案 0 :(得分:1)

问题更可能出现在其他地方,只要downloadPng未被多次同时调用,显示的代码就可以正常工作。

除此之外,在这里创建一个新的promise是没有意义的,因为request.get已经返回一个Promise,而不是Sync,你应该使用一个promisified版本的write命令:

const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs'))

function downloadPng(url) {
  return request.get({
      url: url,
      headers: header,
      encoding: 'binary',
    }).then(res => {
      return fs.writeFileAsync('fileName', res, 'binary')
    })
    .then(() => {
      return foo('fileName') //my function using fileName
    })
})

如果您可以使用awaitasync,则可以这样写:

const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs'))

async function downloadPng(url) {
  var res = await request.get({
    url: url,
    headers: header,
    encoding: 'binary',
  });

  await fs.writeFileAsync('fileName', res, 'binary')

  return foo('fileName')
})