2016-05-04 59 views
0

我目前正在转换构建过程与一些回拨地狱进入承诺地狱(地狱最有可能是由于我是承诺和我与蓝鸟的经验不足)。我正努力克服.all方法的错误,即文件已经存在。或许其中的文件副本试图在开始之前发生在rimraf之前?使用回调地狱转换构建承诺地狱

const Promise = require('bluebird'); 
const rcopyAsync = Promise.promisify(require('recursive-copy')); 
const readAsync = Promise.promisify(require('recursive-readdir')); 
const rmrfAsync = Promise.promisify(require('rimraf')); 
const globAsync = Promise.promisify(require('glob')); 

rmrfAsync('{build,dist}') 
    .then(() => { 
     return readAsync('src'); 
    }) 
    .then((files) => { 
     if (!files.length) { 
      return Promise.reject(new Error('No source to compile.')); 
     } 

     return Promise.resolve(true); 
    }) 
    .all([ 
     rcopyAsync(`${__dirname}/scripting`, 'build'), 
     rcopyAsync(`${__dirname}/compiler/${process.platform}`, 'build'), 
     rcopyAsync('src/scripting', 'build') 
    ]) 
    .then(() => { 
     return globAsync('*.sma', { cwd: 'build' }); 
    }) 
    .then((files) => { 
     console.log(files); 
    }) 
    .catch(err => { 
     throw err; 
    }); 

任何有兴趣,回调地狱的工作部分是如下:

... 

rmrf('{build,dist}', err => { 
    if (err) throw err; 

    read('src', (err, files) => { 
     if (err) throw err; 
     if (!files.length) return; 

     rcopy(`${__dirname}/scripting`, 'build', err => { 
      if (err) throw err; 

      rcopy(`${__dirname}/compiler/${process.platform}`, 'build', err => { 
       if (err) throw err; 

       rcopy('src/scripting', 'build', err => { 
        if (err) throw err; 

        glob('*.sma', { cwd: 'build' }, (err, files) => { 
         if (err) throw err; 

         console.log(files); 
        }); 
       }); 
      }); 
     }); 
    }); 
}); 

回答

3

您正在诺言是如何工作的欺骗。当你第一次执行你的JavaScript时,链的所有部分都被构建。因为在建立您的连锁店时,您会拨打rcopyAsyncrcopyAsync将立即开始。如果您希望稍后发生某种情况,则需要将其包装在.then中。

rmrfAsync('{build,dist}') 
.then(() => { 
    return readAsync('src'); 
}) 
.then((files) => { 
    if (!files.length) { 
     /* Could even be: 
     throw new Error('No source to compile'); 
     */ 
     return Promise.reject(new Error('No source to compile.')); 
    } 
}) 
.then(() => { 
    // Wait until the previous promise finished before starting the rcopyAsync 
    return Promise.all([ 
     rcopyAsync(`${__dirname}/scripting`, 'build'), 
     rcopyAsync(`${__dirname}/compiler/${process.platform}`, 'build'), 
     rcopyAsync('src/scripting', 'build') 
    ]); 
}) 
... 

您想推迟执行。如果您在函数包装器外执行某些操作,那么它将立即执行。如果将其放入函数包装器中,则只有在前一个调用完成后才会执行它。

+0

的'返回Promise.resolve(真);'不会出现需要。 – jfriend00

+0

我原来只是c&p的来源。我把它清理了一下。 – Strikeskids

+1

优秀的描述。教一个人去钓鱼。 – tenub

0

ES2017有async/await语法

为了防止Promise hell

所以,你的代码应该是

async function foo() { 
    await rmrfAsync('{build,dist}') 

    var files = await readAsync('src') 
    if (!files.length) 
     throw new Error('No source to compile.'); 

    await Promise.all([ 
     rcopyAsync(`${__dirname}/scripting`, 'build'), 
     rcopyAsync(`${__dirname}/compiler/${process.platform}`, 'build'), 
     rcopyAsync('src/scripting', 'build') 
    ]) 
    var files = await globAsync('*.sma', { cwd: 'build' }) 
    console.log(files) 
    return files 
} 

foo() 
.then(files => something(files)) 
.catch(e => console.log('throw errors or rejecteds'))