2016-05-04 8 views
0

私は現在、いくつかのコールバック地獄でビルドプロセスを約束地獄に変えています(私は約束の新しさと私のブルーバードの経験がないためです)。私はファイルが既に存在するというエラーで.allメソッドを抜け出すのに苦労しています。ファイル内のファイルコピーが、開始時にrimrafより前に実行されている可能性がありますか?興味がある人々のためにコールバックhellを使って地獄を約束してビルドを変換する

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を実行すると、チェーンのすべての部分が構築されます。あなたのチェーンを構築するにはrcopyAsyncと呼ぶので、すぐにrcopyAsyncが始まります。後で何かをしたい場合は、.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だからPromise hell

を防止するためにasync/await構文

を持って、あなたのコードは

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')) 
関連する問題